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 Erase an object from OwnerContainer using discard queue
109 * @param container to remove from
110 * @param object to remove
111 * @param discardQueue to put the object to
112 * @param updateBufferIndex to use
115 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
117 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
119 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
120 for( auto&& iter : container )
122 if ( iter == object )
124 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
125 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
126 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
132 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
133 * @param[in] node The node whose hierarchy to descend
135 void SortSiblingNodesRecursively( Node& node )
137 NodeContainer& container = node.GetChildren();
138 std::sort( container.Begin(), container.End(),
139 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
141 // Descend tree and sort as well
142 for( auto&& iter : container )
144 SortSiblingNodesRecursively( *iter );
148 } // unnamed namespace
151 * Structure to contain UpdateManager internal data
153 struct UpdateManager::Impl
155 Impl( NotificationManager& notificationManager,
156 CompleteNotificationInterface& animationPlaylist,
157 PropertyNotifier& propertyNotifier,
158 DiscardQueue& discardQueue,
159 RenderController& renderController,
160 RenderManager& renderManager,
161 RenderQueue& renderQueue,
162 SceneGraphBuffers& sceneGraphBuffers,
163 RenderTaskProcessor& renderTaskProcessor )
164 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
165 notificationManager( notificationManager ),
167 animationPlaylist( animationPlaylist ),
168 propertyNotifier( propertyNotifier ),
170 discardQueue( discardQueue ),
171 renderController( renderController ),
172 sceneController( NULL ),
173 renderManager( renderManager ),
174 renderQueue( renderQueue ),
175 renderInstructions( renderManager.GetRenderInstructionContainer() ),
176 renderTaskProcessor( renderTaskProcessor ),
177 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
181 panGestureProcessor( NULL ),
182 messageQueue( renderController, sceneGraphBuffers ),
183 frameCallbackProcessor( NULL ),
184 keepRenderingSeconds( 0.0f ),
185 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
187 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
188 animationFinishedDuringUpdate( false ),
189 previousUpdateScene( false ),
190 renderTaskWaiting( false ),
191 renderersAdded( false ),
192 surfaceRectChanged( false )
194 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
196 // create first 'dummy' node
202 // Disconnect render tasks from nodes, before destroying the nodes
203 for( auto taskList : taskLists )
205 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
206 for ( auto&& task : tasks )
208 task->SetSourceNode( NULL );
212 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
213 // like custom properties, which get released here
214 Vector<Node*>::Iterator iter = nodes.Begin()+1;
215 Vector<Node*>::Iterator endIter = nodes.End();
216 for(;iter!=endIter;++iter)
218 (*iter)->OnDestroy();
222 for( auto root : roots )
227 delete sceneController;
231 * Lazy init for FrameCallbackProcessor.
232 * @param[in] updateManager A reference to the update-manager
234 FrameCallbackProcessor& GetFrameCallbackProcessor( UpdateManager& updateManager )
236 if( ! frameCallbackProcessor )
238 frameCallbackProcessor = new FrameCallbackProcessor( updateManager, transformManager );
240 return *frameCallbackProcessor;
243 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
244 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
245 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
246 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
247 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
248 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
249 ShaderSaver* shaderSaver; ///< Saves shader binaries.
250 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
251 RenderController& renderController; ///< render controller
252 SceneControllerImpl* sceneController; ///< scene controller
253 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
254 RenderQueue& renderQueue; ///< Used to queue messages for the next render
255 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
256 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
258 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
260 OwnerContainer<RenderTaskList*> taskLists; ///< A container of scene graph render task lists
262 OwnerContainer<Layer*> roots; ///< A container of root nodes (root is a layer). The layers are not stored in the node memory pool.
264 Vector<Node*> nodes; ///< A container of all instantiated nodes
266 std::vector<SortedLayerPointers> sortedLayerLists; ///< A container of lists of Layer pointers sorted by depth (one list of sorted layers per root)
268 OwnerContainer< Camera* > cameras; ///< A container of cameras
269 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
271 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
272 OwnerContainer< Animation* > animations; ///< A container of owned animations
273 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
274 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
275 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
276 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
277 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
279 MessageQueue messageQueue; ///< The messages queued from the event-thread
280 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
281 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
282 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
284 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
286 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
287 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
288 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
290 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
292 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
293 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
294 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
295 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
296 bool surfaceRectChanged; ///< True if the default surface rect is changed
300 Impl( const Impl& ); ///< Undefined
301 Impl& operator=( const Impl& ); ///< Undefined
304 UpdateManager::UpdateManager( NotificationManager& notificationManager,
305 CompleteNotificationInterface& animationFinishedNotifier,
306 PropertyNotifier& propertyNotifier,
307 DiscardQueue& discardQueue,
308 RenderController& controller,
309 RenderManager& renderManager,
310 RenderQueue& renderQueue,
311 RenderTaskProcessor& renderTaskProcessor )
314 mImpl = new Impl( notificationManager,
315 animationFinishedNotifier,
322 renderTaskProcessor );
326 UpdateManager::~UpdateManager()
331 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
333 DALI_ASSERT_DEBUG( layer->IsLayer() );
334 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
336 Layer* rootLayer = layer.Release();
338 DALI_ASSERT_DEBUG( std::find( mImpl->roots.begin(), mImpl->roots.end(), rootLayer ) == mImpl->roots.end() && "Root Node already installed" );
340 rootLayer->CreateTransform( &mImpl->transformManager );
341 rootLayer->SetRoot(true);
342 mImpl->roots.PushBack( rootLayer );
345 void UpdateManager::AddNode( OwnerPointer<Node>& node )
347 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
349 // Nodes must be sorted by pointer
350 Node* rawNode = node.Release();
351 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
352 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
354 if( rawNode > (*iter) )
356 mImpl->nodes.Insert((iter+1), rawNode );
357 rawNode->CreateTransform( &mImpl->transformManager );
363 void UpdateManager::ConnectNode( Node* parent, Node* node )
365 DALI_ASSERT_ALWAYS( NULL != parent );
366 DALI_ASSERT_ALWAYS( NULL != node );
367 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
369 parent->ConnectChild( node );
371 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
372 if( mImpl->frameCallbackProcessor )
374 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
378 void UpdateManager::DisconnectNode( Node* node )
380 Node* parent = node->GetParent();
381 DALI_ASSERT_ALWAYS( NULL != parent );
382 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
384 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
386 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
387 if( mImpl->frameCallbackProcessor )
389 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
393 void UpdateManager::DestroyNode( Node* node )
395 DALI_ASSERT_ALWAYS( NULL != node );
396 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
398 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
399 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
400 for(;iter!=endIter;++iter)
404 mImpl->nodes.Erase(iter);
409 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
411 // Notify the Node about impending destruction
415 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
417 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
420 void UpdateManager::RemoveCamera( Camera* camera )
422 // Find the camera and destroy it
423 EraseUsingDiscardQueue( mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
426 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
428 mImpl->customObjects.PushBack( object.Release() );
431 void UpdateManager::RemoveObject( PropertyOwner* object )
433 mImpl->customObjects.EraseObject( object );
436 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
438 RenderTaskList* taskListPointer = taskList.Release();
439 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
440 mImpl->taskLists.PushBack( taskListPointer );
443 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
445 mImpl->taskLists.EraseObject( taskList );
448 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
450 mImpl->animations.PushBack( animation.Release() );
453 void UpdateManager::StopAnimation( Animation* animation )
455 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
457 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
459 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
462 void UpdateManager::RemoveAnimation( Animation* animation )
464 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
466 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
468 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
471 bool UpdateManager::IsAnimationRunning() const
473 // Find any animation that isn't stopped or paused
474 for ( auto&& iter : mImpl->animations )
476 const Animation::State state = iter->GetState();
478 if (state != Animation::Stopped &&
479 state != Animation::Paused)
481 return true; // stop iteration as soon as first one is found
488 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
490 propertyResetter->Initialize();
491 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
494 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
496 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
499 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
501 mImpl->propertyNotifications.EraseObject( propertyNotification );
504 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
506 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
507 propertyNotification->SetNotifyMode( notifyMode );
510 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
512 mImpl->shaders.PushBack( shader.Release() );
515 void UpdateManager::RemoveShader( Shader* shader )
517 // Find the shader and destroy it
518 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
521 void UpdateManager::SetShaderProgram( Shader* shader,
522 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
527 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
529 // Reserve some memory inside the render queue
530 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
532 // Construct message in the render queue memory; note that delete should not be called on the return value
533 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
537 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
539 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
540 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
542 // lock as update might be sending previously compiled shaders to event thread
543 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
544 mImpl->renderCompiledShaders.push_back( shaderData );
548 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
550 mImpl->shaderSaver = &upstream;
553 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
555 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
556 mImpl->renderers.PushBack( renderer.Release() );
557 mImpl->renderersAdded = true;
560 void UpdateManager::RemoveRenderer( Renderer* renderer )
562 // Find the renderer and destroy it
563 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
564 // Need to remove the render object as well
565 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
568 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
570 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
572 mImpl->panGestureProcessor = panGestureProcessor;
575 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
577 mImpl->textureSets.PushBack( textureSet.Release() );
580 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
582 mImpl->textureSets.EraseObject( textureSet );
585 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
587 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
590 void UpdateManager::EventProcessingStarted()
592 mImpl->messageQueue.EventProcessingStarted();
595 bool UpdateManager::FlushQueue()
597 return mImpl->messageQueue.FlushQueue();
600 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
602 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
603 mImpl->animationFinishedDuringUpdate = false;
605 // Reset all animating / constrained properties
606 std::vector<PropertyResetterBase*>toDelete;
607 for( auto&& element : mImpl->propertyResetters )
609 element->ResetToBaseValue( bufferIndex );
610 if( element->IsFinished() )
612 toDelete.push_back( element );
616 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
617 for( auto&& elementPtr : toDelete )
619 mImpl->propertyResetters.EraseObject( elementPtr );
622 // Clear node dirty flags
623 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
624 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
625 for( ;iter != endIter; ++iter )
627 (*iter)->ResetDirtyFlags( bufferIndex );
631 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
633 bool gestureUpdated( false );
635 if( mImpl->panGestureProcessor )
637 // gesture processor only supports default properties
638 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
639 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
642 return gestureUpdated;
645 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
647 auto&& iter = mImpl->animations.Begin();
648 bool animationLooped = false;
650 while ( iter != mImpl->animations.End() )
652 Animation* animation = *iter;
653 bool finished = false;
655 bool progressMarkerReached = false;
656 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
658 if ( progressMarkerReached )
660 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
663 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
664 animationLooped = animationLooped || looped;
666 // Remove animations that had been destroyed but were still waiting for an update
667 if (animation->GetState() == Animation::Destroyed)
669 iter = mImpl->animations.Erase(iter);
677 // queue the notification on finished or looped (to update loop count)
678 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
680 // The application should be notified by NotificationManager, in another thread
681 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
685 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
687 //Constrain custom objects (in construction order)
688 for ( auto&& object : mImpl->customObjects )
690 ConstrainPropertyOwner( *object, bufferIndex );
694 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
696 // Constrain render-tasks
697 for( auto taskList : mImpl->taskLists )
699 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
700 for ( auto&& task : tasks )
702 ConstrainPropertyOwner( *task, bufferIndex );
707 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
709 // constrain shaders... (in construction order)
710 for ( auto&& shader : mImpl->shaders )
712 ConstrainPropertyOwner( *shader, bufferIndex );
716 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
718 for( auto&& notification : mImpl->propertyNotifications )
720 bool valid = notification->Check( bufferIndex );
723 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
728 void UpdateManager::ForwardCompiledShadersToEventThread()
730 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
731 if( mImpl->shaderSaver )
733 // lock and swap the queues
735 // render might be attempting to send us more binaries at the same time
736 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
737 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
740 if( mImpl->updateCompiledShaders.size() > 0 )
742 ShaderSaver& factory = *mImpl->shaderSaver;
743 for( auto&& shader : mImpl->updateCompiledShaders )
745 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
747 // we don't need them in update anymore
748 mImpl->updateCompiledShaders.clear();
753 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
755 for( auto&& renderer : mImpl->renderers )
758 ConstrainPropertyOwner( *renderer, bufferIndex );
760 renderer->PrepareRender( bufferIndex );
764 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
766 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
768 for( auto&& rootLayer : mImpl->roots )
770 // Prepare resources, update shaders, for each node
771 // And add the renderers to the sorted layers. Start from root, which is also a layer
772 mImpl->nodeDirtyFlags |= UpdateNodeTree( *rootLayer,
774 mImpl->renderQueue );
778 uint32_t UpdateManager::Update( float elapsedSeconds,
779 uint32_t lastVSyncTimeMilliseconds,
780 uint32_t nextVSyncTimeMilliseconds,
781 bool renderToFboEnabled,
782 bool isRenderingToFbo )
784 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
786 //Clear nodes/resources which were previously discarded
787 mImpl->discardQueue.Clear( bufferIndex );
789 //Process Touches & Gestures
790 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
792 bool updateScene = // The scene-graph requires an update if..
793 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
794 IsAnimationRunning() || // ..at least one animation is running OR
795 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
796 gestureUpdated; // ..a gesture property was updated
798 bool keepRendererRendering = false;
800 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
801 // values if the scene was updated in the previous frame.
802 if( updateScene || mImpl->previousUpdateScene )
804 //Reset properties from the previous update
805 ResetProperties( bufferIndex );
806 mImpl->transformManager.ResetToBaseValue();
809 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
810 // between calling IsSceneUpdateRequired() above and here, so updateScene should
812 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
814 //Forward compiled shader programs to event thread for saving
815 ForwardCompiledShadersToEventThread();
817 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
818 // renderer lists if the scene was updated in the previous frame.
819 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
820 if( updateScene || mImpl->previousUpdateScene )
823 Animate( bufferIndex, elapsedSeconds );
825 //Constraint custom objects
826 ConstrainCustomObjects( bufferIndex );
828 //Clear the lists of renderers from the previous update
829 for( auto sortedLayers : mImpl->sortedLayerLists )
831 for( auto&& layer : sortedLayers )
833 layer->ClearRenderables();
837 // Call the frame-callback-processor if set
838 if( mImpl->frameCallbackProcessor )
840 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
843 //Update node hierarchy, apply constraints and perform sorting / culling.
844 //This will populate each Layer with a list of renderers which are ready.
845 UpdateNodes( bufferIndex );
847 //Apply constraints to RenderTasks, shaders
848 ConstrainRenderTasks( bufferIndex );
849 ConstrainShaders( bufferIndex );
851 //Update renderers and apply constraints
852 UpdateRenderers( bufferIndex );
854 //Update the transformations of all the nodes
855 mImpl->transformManager.Update();
857 //Process Property Notifications
858 ProcessPropertyNotifications( bufferIndex );
861 for( auto&& cameraIterator : mImpl->cameras )
863 cameraIterator->Update( bufferIndex );
866 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
867 //reset the update buffer index and make sure there is enough room in the instruction container
868 if( mImpl->renderersAdded )
870 // Calculate how many render tasks we have in total
871 VectorBase::SizeType numberOfRenderTasks = 0;
873 const VectorBase::SizeType taskListCount = mImpl->taskLists.Count();
874 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
876 numberOfRenderTasks += mImpl->taskLists[index]->GetTasks().Count();
879 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
880 static_cast<uint32_t>( numberOfRenderTasks ) );
882 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
884 if ( NULL != mImpl->roots[index] )
886 keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
887 *mImpl->taskLists[index],
888 *mImpl->roots[index],
889 mImpl->sortedLayerLists[index],
890 mImpl->renderInstructions,
898 for( auto taskList : mImpl->taskLists )
900 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
902 // check the countdown and notify
903 bool doRenderOnceNotify = false;
904 mImpl->renderTaskWaiting = false;
905 for ( auto&& renderTask : tasks )
907 renderTask->UpdateState();
909 if( renderTask->IsWaitingToRender() &&
910 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
912 mImpl->renderTaskWaiting = true; // keep update/render threads alive
915 if( renderTask->HasRendered() )
917 doRenderOnceNotify = true;
921 if( doRenderOnceNotify )
923 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
924 mImpl->notificationManager.QueueCompleteNotification( taskList->GetCompleteNotificationInterface() );
928 // Macro is undefined in release build.
929 SNAPSHOT_NODE_LOGGING;
931 // A ResetProperties() may be required in the next frame
932 mImpl->previousUpdateScene = updateScene;
934 // Check whether further updates are required
935 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
937 if( keepRendererRendering )
939 keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
942 // tell the update manager that we're done so the queue can be given to event thread
943 mImpl->notificationManager.UpdateCompleted();
945 // The update has finished; swap the double-buffering indices
946 mSceneGraphBuffers.Swap();
951 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
953 // Update the duration set via Stage::KeepRendering()
954 if ( mImpl->keepRenderingSeconds > 0.0f )
956 mImpl->keepRenderingSeconds -= elapsedSeconds;
959 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
961 // If the rendering behavior is set to continuously render, then continue to render.
962 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
963 // Keep updating until no messages are received and no animations are running.
964 // If an animation has just finished, update at least once more for Discard end-actions.
965 // No need to check for renderQueue as there is always a render after update and if that
966 // render needs another update it will tell the adaptor to call update again
968 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
969 ( mImpl->keepRenderingSeconds > 0.0f ) )
971 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
974 if ( IsAnimationRunning() ||
975 mImpl->animationFinishedDuringUpdate )
977 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
980 if ( mImpl->renderTaskWaiting )
982 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
985 return keepUpdatingRequest;
988 void UpdateManager::SetBackgroundColor( const Vector4& color )
990 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
992 // Reserve some memory inside the render queue
993 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
995 // Construct message in the render queue memory; note that delete should not be called on the return value
996 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
999 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1001 mImpl->surfaceRectChanged = true;
1003 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1005 // Reserve some memory inside the render queue
1006 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1008 // Construct message in the render queue memory; note that delete should not be called on the return value
1009 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1012 void UpdateManager::KeepRendering( float durationSeconds )
1014 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1017 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1019 mImpl->renderingBehavior = renderingBehavior;
1022 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1024 const VectorBase::SizeType rootCount = mImpl->roots.Count();
1026 // Make sure we reserve the correct size for the container so that
1027 // we can save the sorted layers in the same order as the root layer
1028 mImpl->sortedLayerLists.resize( rootCount );
1030 for ( VectorBase::SizeType rootIndex = 0u; rootIndex < rootCount; rootIndex++ )
1032 Layer* root = mImpl->roots[rootIndex];
1033 if ( root == rootLayer )
1035 mImpl->sortedLayerLists[rootIndex] = layers;
1041 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1043 // note,this vector is already in depth order. It could be used as-is to
1044 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1045 for( auto&& iter : nodeDepths->nodeDepths )
1047 iter.node->SetDepthIndex( iter.sortedDepth );
1050 for( auto root : mImpl->roots )
1052 // Go through node hierarchy and rearrange siblings according to depth-index
1053 SortSiblingNodesRecursively( *root );
1057 bool UpdateManager::IsDefaultSurfaceRectChanged()
1059 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1062 mImpl->surfaceRectChanged = false;
1064 return surfaceRectChanged;
1067 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1069 mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
1072 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1074 mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
1077 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1079 // Message has ownership of Sampler while in transit from update to render
1080 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1082 // Reserve some memory inside the render queue
1083 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1085 // Construct message in the render queue memory; note that delete should not be called on the return value
1086 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1089 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1091 typedef MessageValue1< RenderManager, 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::RemoveSampler, sampler );
1100 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1102 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > 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::SetFilterMode, sampler, minFilterMode, magFilterMode );
1111 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1113 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, 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::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1122 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1124 // Message has ownership of format while in transit from update -> render
1125 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1127 // Reserve some memory inside the render queue
1128 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1130 // Construct message in the render queue memory; note that delete should not be called on the return value
1131 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1134 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1136 typedef MessageValue1< RenderManager, 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::RemovePropertyBuffer, propertyBuffer );
1145 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1147 // Message has ownership of format while in transit from update -> render
1148 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1150 // Reserve some memory inside the render queue
1151 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1153 // Construct message in the render queue memory; note that delete should not be called on the return value
1154 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1157 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1159 // Message has ownership of format while in transit from update -> render
1160 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1162 // Reserve some memory inside the render queue
1163 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1165 // Construct message in the render queue memory; note that delete should not be called on the return value
1166 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1169 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1171 // Message has ownership of format while in transit from update -> render
1172 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1174 // Reserve some memory inside the render queue
1175 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1177 // Construct message in the render queue memory; note that delete should not be called on the return value
1178 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1181 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1183 typedef MessageValue1< RenderManager, 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::RemoveGeometry, geometry );
1192 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1194 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > 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::SetGeometryType, geometry, geometryType );
1203 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1205 typedef IndexBufferMessage< RenderManager > 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, geometry, indices );
1214 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1216 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > 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, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1225 void UpdateManager::AttachVertexBuffer( 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::AttachVertexBuffer, geometry, propertyBuffer );
1236 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1238 // Message has ownership of Texture while in transit from update -> render
1239 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1241 // Reserve some memory inside the render queue
1242 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1244 // Construct message in the render queue memory; note that delete should not be called on the return value
1245 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1248 void UpdateManager::RemoveTexture( Render::Texture* texture)
1250 typedef MessageValue1< RenderManager, 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::RemoveTexture, texture );
1259 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1261 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1263 // Reserve some memory inside the message queue
1264 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1266 // Construct message in the message queue memory; note that delete should not be called on the return value
1267 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1270 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1272 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1274 // Reserve some memory inside the render queue
1275 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1277 // Construct message in the render queue memory; note that delete should not be called on the return value
1278 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1281 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1283 typedef MessageValue1< RenderManager, Render::FrameBuffer* > 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::AddFrameBuffer, frameBuffer );
1292 void UpdateManager::RemoveFrameBuffer( 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::RemoveFrameBuffer, frameBuffer );
1303 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1305 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > 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::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1314 } // namespace SceneGraph
1316 } // namespace Internal