2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/owner-container.h>
24 #include <dali/devel-api/threading/mutex.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/render-controller.h>
28 #include <dali/internal/common/shader-data.h>
29 #include <dali/integration-api/debug.h>
31 #include <dali/internal/common/core-impl.h>
32 #include <dali/internal/common/message.h>
34 #include <dali/internal/event/common/notification-manager.h>
35 #include <dali/internal/event/common/property-notification-impl.h>
36 #include <dali/internal/event/common/property-notifier.h>
37 #include <dali/internal/event/effects/shader-factory.h>
38 #include <dali/internal/event/animation/animation-playlist.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/scene-graph-buffers.h>
44 #include <dali/internal/update/controllers/render-message-dispatcher.h>
45 #include <dali/internal/update/controllers/scene-controller-impl.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/frame-callback-processor.h>
48 #include <dali/internal/update/manager/render-task-processor.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/scene-graph-frame-callback.h>
51 #include <dali/internal/update/manager/update-algorithms.h>
52 #include <dali/internal/update/manager/update-manager-debug.h>
53 #include <dali/internal/update/manager/transform-manager.h>
54 #include <dali/internal/update/nodes/node.h>
55 #include <dali/internal/update/nodes/scene-graph-layer.h>
56 #include <dali/internal/update/queue/update-message-queue.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
58 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
59 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
61 #include <dali/internal/render/common/render-instruction-container.h>
62 #include <dali/internal/render/common/render-manager.h>
63 #include <dali/internal/render/queue/render-queue.h>
64 #include <dali/internal/render/shaders/scene-graph-shader.h>
66 // Un-comment to enable node tree debug logging
67 //#define NODE_TREE_LOGGING 1
69 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
70 #define SNAPSHOT_NODE_LOGGING \
71 const uint32_t FRAME_COUNT_TRIGGER = 16;\
72 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
74 for( auto 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;
92 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_UPDATE_MANAGER" );
93 } // unnamed namespace
97 using namespace Dali::Integration;
98 using Dali::Internal::Update::MessageQueue;
112 * Helper to Erase an object from OwnerContainer using discard queue
113 * @param container to remove from
114 * @param object to remove
115 * @param discardQueue to put the object to
116 * @param updateBufferIndex to use
119 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
121 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
123 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
124 for( auto&& iter : container )
126 if ( iter == object )
128 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
129 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
130 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
136 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
137 * @param[in] node The node whose hierarchy to descend
139 void SortSiblingNodesRecursively( Node& node )
141 NodeContainer& container = node.GetChildren();
142 std::sort( container.Begin(), container.End(),
143 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
145 // Descend tree and sort as well
146 for( auto&& iter : container )
148 SortSiblingNodesRecursively( *iter );
152 } // unnamed namespace
155 * Structure to contain UpdateManager internal data
157 struct UpdateManager::Impl
159 Impl( NotificationManager& notificationManager,
160 CompleteNotificationInterface& animationPlaylist,
161 PropertyNotifier& propertyNotifier,
162 DiscardQueue& discardQueue,
163 RenderController& renderController,
164 RenderManager& renderManager,
165 RenderQueue& renderQueue,
166 SceneGraphBuffers& sceneGraphBuffers,
167 RenderTaskProcessor& renderTaskProcessor )
168 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
169 notificationManager( notificationManager ),
171 animationPlaylist( animationPlaylist ),
172 propertyNotifier( propertyNotifier ),
174 discardQueue( discardQueue ),
175 renderController( renderController ),
176 sceneController( NULL ),
177 renderManager( renderManager ),
178 renderQueue( renderQueue ),
179 renderInstructions( renderManager.GetRenderInstructionContainer() ),
180 renderTaskProcessor( renderTaskProcessor ),
181 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
185 panGestureProcessor( NULL ),
186 messageQueue( renderController, sceneGraphBuffers ),
187 frameCallbackProcessor( NULL ),
188 keepRenderingSeconds( 0.0f ),
189 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
191 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
192 animationFinishedDuringUpdate( false ),
193 previousUpdateScene( false ),
194 renderTaskWaiting( false ),
195 renderersAdded( false ),
196 surfaceRectChanged( false )
198 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
200 // create first 'dummy' node
206 // Disconnect render tasks from nodes, before destroying the nodes
207 for( auto taskList : taskLists )
209 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
210 for ( auto&& task : tasks )
212 task->SetSourceNode( NULL );
216 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
217 // like custom properties, which get released here
218 Vector<Node*>::Iterator iter = nodes.Begin()+1;
219 Vector<Node*>::Iterator endIter = nodes.End();
220 for(;iter!=endIter;++iter)
222 (*iter)->OnDestroy();
226 for( auto root : roots )
232 delete sceneController;
236 * Lazy init for FrameCallbackProcessor.
237 * @param[in] updateManager A reference to the update-manager
239 FrameCallbackProcessor& GetFrameCallbackProcessor( UpdateManager& updateManager )
241 if( ! frameCallbackProcessor )
243 frameCallbackProcessor = new FrameCallbackProcessor( updateManager, transformManager );
245 return *frameCallbackProcessor;
248 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
249 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
250 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
251 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
252 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
253 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
254 ShaderSaver* shaderSaver; ///< Saves shader binaries.
255 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
256 RenderController& renderController; ///< render controller
257 SceneControllerImpl* sceneController; ///< scene controller
258 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
259 RenderQueue& renderQueue; ///< Used to queue messages for the next render
260 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
261 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
263 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
265 OwnerContainer<RenderTaskList*> taskLists; ///< A container of scene graph render task lists
267 Vector<Layer*> roots; ///< A container of root nodes (root is a layer). The layers are not stored in the node memory pool.
269 Vector<Node*> nodes; ///< A container of all instantiated nodes
271 std::vector<SortedLayerPointers> sortedLayerLists; ///< A container of lists of Layer pointers sorted by depth (one list of sorted layers per root)
273 OwnerContainer< Camera* > cameras; ///< A container of cameras
274 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
276 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
277 OwnerContainer< Animation* > animations; ///< A container of owned animations
278 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
279 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
280 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
281 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
282 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
284 MessageQueue messageQueue; ///< The messages queued from the event-thread
285 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
286 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
287 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
289 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
291 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
292 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
293 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
295 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
297 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
298 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
299 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
300 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
301 bool surfaceRectChanged; ///< True if the default surface rect is changed
305 Impl( const Impl& ); ///< Undefined
306 Impl& operator=( const Impl& ); ///< Undefined
309 UpdateManager::UpdateManager( NotificationManager& notificationManager,
310 CompleteNotificationInterface& animationFinishedNotifier,
311 PropertyNotifier& propertyNotifier,
312 DiscardQueue& discardQueue,
313 RenderController& controller,
314 RenderManager& renderManager,
315 RenderQueue& renderQueue,
316 RenderTaskProcessor& renderTaskProcessor )
319 mImpl = new Impl( notificationManager,
320 animationFinishedNotifier,
327 renderTaskProcessor );
331 UpdateManager::~UpdateManager()
336 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
338 DALI_ASSERT_DEBUG( layer->IsLayer() );
339 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
341 Layer* rootLayer = layer.Release();
343 DALI_ASSERT_DEBUG( std::find( mImpl->roots.begin(), mImpl->roots.end(), rootLayer ) == mImpl->roots.end() && "Root Node already installed" );
345 rootLayer->CreateTransform( &mImpl->transformManager );
346 rootLayer->SetRoot(true);
347 mImpl->roots.PushBack( rootLayer );
350 void UpdateManager::UninstallRoot( Layer* layer )
352 DALI_ASSERT_DEBUG( layer->IsLayer() );
353 DALI_ASSERT_DEBUG( layer->GetParent() == NULL );
355 for ( auto&& iter : mImpl->roots )
357 if( ( *iter ) == layer )
359 mImpl->roots.Erase( &iter );
364 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), layer );
366 // Notify the layer about impending destruction
370 void UpdateManager::AddNode( OwnerPointer<Node>& node )
372 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
374 // Nodes must be sorted by pointer
375 Node* rawNode = node.Release();
376 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddNode\n", rawNode );
378 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
379 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
381 if( rawNode > (*iter) )
383 mImpl->nodes.Insert((iter+1), rawNode );
384 rawNode->CreateTransform( &mImpl->transformManager );
390 void UpdateManager::ConnectNode( Node* parent, Node* node )
392 DALI_ASSERT_ALWAYS( NULL != parent );
393 DALI_ASSERT_ALWAYS( NULL != node );
394 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
396 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] ConnectNode\n", node );
398 parent->ConnectChild( node );
400 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
401 if( mImpl->frameCallbackProcessor )
403 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
407 void UpdateManager::DisconnectNode( Node* node )
409 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DisconnectNode\n", node );
411 Node* parent = node->GetParent();
412 DALI_ASSERT_ALWAYS( NULL != parent );
413 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
415 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
417 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
418 if( mImpl->frameCallbackProcessor )
420 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
424 void UpdateManager::DestroyNode( Node* node )
426 DALI_ASSERT_ALWAYS( NULL != node );
427 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
429 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DestroyNode\n", node );
431 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
432 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
433 for(;iter!=endIter;++iter)
437 mImpl->nodes.Erase(iter);
442 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
444 // Notify the Node about impending destruction
448 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
450 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
453 void UpdateManager::RemoveCamera( Camera* camera )
455 // Find the camera and destroy it
456 EraseUsingDiscardQueue( mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
459 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
461 mImpl->customObjects.PushBack( object.Release() );
464 void UpdateManager::RemoveObject( PropertyOwner* object )
466 mImpl->customObjects.EraseObject( object );
469 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
471 RenderTaskList* taskListPointer = taskList.Release();
472 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
473 mImpl->taskLists.PushBack( taskListPointer );
476 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
478 mImpl->taskLists.EraseObject( taskList );
481 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
483 mImpl->animations.PushBack( animation.Release() );
486 void UpdateManager::StopAnimation( Animation* animation )
488 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
490 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
492 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
495 void UpdateManager::RemoveAnimation( Animation* animation )
497 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
499 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
501 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
504 bool UpdateManager::IsAnimationRunning() const
506 // Find any animation that isn't stopped or paused
507 for ( auto&& iter : mImpl->animations )
509 const Animation::State state = iter->GetState();
511 if (state != Animation::Stopped &&
512 state != Animation::Paused)
514 return true; // stop iteration as soon as first one is found
521 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
523 propertyResetter->Initialize();
524 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
527 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
529 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
532 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
534 mImpl->propertyNotifications.EraseObject( propertyNotification );
537 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
539 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
540 propertyNotification->SetNotifyMode( notifyMode );
543 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
545 mImpl->shaders.PushBack( shader.Release() );
548 void UpdateManager::RemoveShader( Shader* shader )
550 // Find the shader and destroy it
551 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
554 void UpdateManager::SetShaderProgram( Shader* shader,
555 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
560 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
562 // Reserve some memory inside the render queue
563 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
565 // Construct message in the render queue memory; note that delete should not be called on the return value
566 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
570 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
572 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
573 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
575 // lock as update might be sending previously compiled shaders to event thread
576 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
577 mImpl->renderCompiledShaders.push_back( shaderData );
581 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
583 mImpl->shaderSaver = &upstream;
586 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
588 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer.Get() );
590 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
591 mImpl->renderers.PushBack( renderer.Release() );
592 mImpl->renderersAdded = true;
595 void UpdateManager::RemoveRenderer( Renderer* renderer )
597 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer );
599 // Find the renderer and destroy it
600 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
601 // Need to remove the render object as well
602 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
605 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
607 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
609 mImpl->panGestureProcessor = panGestureProcessor;
612 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
614 mImpl->textureSets.PushBack( textureSet.Release() );
617 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
619 mImpl->textureSets.EraseObject( textureSet );
622 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
624 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
627 void UpdateManager::EventProcessingStarted()
629 mImpl->messageQueue.EventProcessingStarted();
632 bool UpdateManager::FlushQueue()
634 return mImpl->messageQueue.FlushQueue();
637 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
639 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
640 mImpl->animationFinishedDuringUpdate = false;
642 // Reset all animating / constrained properties
643 std::vector<PropertyResetterBase*>toDelete;
644 for( auto&& element : mImpl->propertyResetters )
646 element->ResetToBaseValue( bufferIndex );
647 if( element->IsFinished() )
649 toDelete.push_back( element );
653 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
654 for( auto&& elementPtr : toDelete )
656 mImpl->propertyResetters.EraseObject( elementPtr );
659 // Clear node dirty flags
660 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
661 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
662 for( ;iter != endIter; ++iter )
664 (*iter)->ResetDirtyFlags( bufferIndex );
668 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
670 bool gestureUpdated( false );
672 if( mImpl->panGestureProcessor )
674 // gesture processor only supports default properties
675 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
676 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
679 return gestureUpdated;
682 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
684 auto&& iter = mImpl->animations.Begin();
685 bool animationLooped = false;
687 while ( iter != mImpl->animations.End() )
689 Animation* animation = *iter;
690 bool finished = false;
692 bool progressMarkerReached = false;
693 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
695 if ( progressMarkerReached )
697 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
700 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
701 animationLooped = animationLooped || looped;
703 // Remove animations that had been destroyed but were still waiting for an update
704 if (animation->GetState() == Animation::Destroyed)
706 iter = mImpl->animations.Erase(iter);
714 // queue the notification on finished or looped (to update loop count)
715 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
717 // The application should be notified by NotificationManager, in another thread
718 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
722 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
724 //Constrain custom objects (in construction order)
725 for ( auto&& object : mImpl->customObjects )
727 ConstrainPropertyOwner( *object, bufferIndex );
731 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
733 // Constrain render-tasks
734 for( auto taskList : mImpl->taskLists )
736 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
737 for ( auto&& task : tasks )
739 ConstrainPropertyOwner( *task, bufferIndex );
744 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
746 // constrain shaders... (in construction order)
747 for ( auto&& shader : mImpl->shaders )
749 ConstrainPropertyOwner( *shader, bufferIndex );
753 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
755 for( auto&& notification : mImpl->propertyNotifications )
757 bool valid = notification->Check( bufferIndex );
760 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
765 void UpdateManager::ForwardCompiledShadersToEventThread()
767 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
768 if( mImpl->shaderSaver )
770 // lock and swap the queues
772 // render might be attempting to send us more binaries at the same time
773 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
774 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
777 if( mImpl->updateCompiledShaders.size() > 0 )
779 ShaderSaver& factory = *mImpl->shaderSaver;
780 for( auto&& shader : mImpl->updateCompiledShaders )
782 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
784 // we don't need them in update anymore
785 mImpl->updateCompiledShaders.clear();
790 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
792 for( auto&& renderer : mImpl->renderers )
795 ConstrainPropertyOwner( *renderer, bufferIndex );
797 renderer->PrepareRender( bufferIndex );
801 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
803 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
805 for( auto&& rootLayer : mImpl->roots )
807 // Prepare resources, update shaders, for each node
808 // And add the renderers to the sorted layers. Start from root, which is also a layer
809 mImpl->nodeDirtyFlags |= UpdateNodeTree( *rootLayer,
811 mImpl->renderQueue );
815 uint32_t UpdateManager::Update( float elapsedSeconds,
816 uint32_t lastVSyncTimeMilliseconds,
817 uint32_t nextVSyncTimeMilliseconds,
818 bool renderToFboEnabled,
819 bool isRenderingToFbo )
821 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
823 //Clear nodes/resources which were previously discarded
824 mImpl->discardQueue.Clear( bufferIndex );
826 //Process Touches & Gestures
827 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
829 bool updateScene = // The scene-graph requires an update if..
830 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
831 IsAnimationRunning() || // ..at least one animation is running OR
832 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
833 gestureUpdated; // ..a gesture property was updated
835 bool keepRendererRendering = false;
837 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
838 // values if the scene was updated in the previous frame.
839 if( updateScene || mImpl->previousUpdateScene )
841 //Reset properties from the previous update
842 ResetProperties( bufferIndex );
843 mImpl->transformManager.ResetToBaseValue();
846 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
847 // between calling IsSceneUpdateRequired() above and here, so updateScene should
849 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
851 //Forward compiled shader programs to event thread for saving
852 ForwardCompiledShadersToEventThread();
854 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
855 // renderer lists if the scene was updated in the previous frame.
856 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
857 if( updateScene || mImpl->previousUpdateScene )
860 Animate( bufferIndex, elapsedSeconds );
862 //Constraint custom objects
863 ConstrainCustomObjects( bufferIndex );
865 //Clear the lists of renderers from the previous update
866 for( auto sortedLayers : mImpl->sortedLayerLists )
868 for( auto&& layer : sortedLayers )
870 layer->ClearRenderables();
874 // Call the frame-callback-processor if set
875 if( mImpl->frameCallbackProcessor )
877 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
880 //Update node hierarchy, apply constraints and perform sorting / culling.
881 //This will populate each Layer with a list of renderers which are ready.
882 UpdateNodes( bufferIndex );
884 //Apply constraints to RenderTasks, shaders
885 ConstrainRenderTasks( bufferIndex );
886 ConstrainShaders( bufferIndex );
888 //Update renderers and apply constraints
889 UpdateRenderers( bufferIndex );
891 //Update the transformations of all the nodes
892 mImpl->transformManager.Update();
894 //Process Property Notifications
895 ProcessPropertyNotifications( bufferIndex );
898 for( auto&& cameraIterator : mImpl->cameras )
900 cameraIterator->Update( bufferIndex );
903 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
904 //reset the update buffer index and make sure there is enough room in the instruction container
905 if( mImpl->renderersAdded )
907 // Calculate how many render tasks we have in total
908 VectorBase::SizeType numberOfRenderTasks = 0;
910 const VectorBase::SizeType taskListCount = mImpl->taskLists.Count();
911 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
913 numberOfRenderTasks += mImpl->taskLists[index]->GetTasks().Count();
916 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
917 static_cast<uint32_t>( numberOfRenderTasks ) );
919 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
921 if ( NULL != mImpl->roots[index] )
923 keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
924 *mImpl->taskLists[index],
925 *mImpl->roots[index],
926 mImpl->sortedLayerLists[index],
927 mImpl->renderInstructions,
933 DALI_LOG_INFO( gLogFilter, Debug::General,
934 "Update: numberOfRenderTasks(%d), taskListCount(%d), Render Instructions(%d)\n",
935 numberOfRenderTasks, taskListCount, mImpl->renderInstructions.Count( bufferIndex ) );
939 // If any node is dirty, i.e. a property has changed or a child has been deleted, and we do not have any instructions to send, then generate a dummy instruction to force another render
940 if( ( mImpl->nodeDirtyFlags != NodePropertyFlags::NOTHING ) && ( mImpl->renderInstructions.Count( bufferIndex ) == 0 ) )
942 DALI_LOG_INFO( gLogFilter, Debug::General, "Node flags dirty, creating dummy instruction\n" );
943 mImpl->renderInstructions.GetNextInstruction( bufferIndex ); // This creates and adds an empty instruction. We do not need to modify it.
948 for( auto taskList : mImpl->taskLists )
950 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
952 // check the countdown and notify
953 bool doRenderOnceNotify = false;
954 mImpl->renderTaskWaiting = false;
955 for ( auto&& renderTask : tasks )
957 renderTask->UpdateState();
959 if( renderTask->IsWaitingToRender() &&
960 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
962 mImpl->renderTaskWaiting = true; // keep update/render threads alive
965 if( renderTask->HasRendered() )
967 doRenderOnceNotify = true;
971 if( doRenderOnceNotify )
973 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
974 mImpl->notificationManager.QueueCompleteNotification( taskList->GetCompleteNotificationInterface() );
978 // Macro is undefined in release build.
979 SNAPSHOT_NODE_LOGGING;
981 // A ResetProperties() may be required in the next frame
982 mImpl->previousUpdateScene = updateScene;
984 // Check whether further updates are required
985 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
987 if( keepRendererRendering )
989 keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
992 // tell the update manager that we're done so the queue can be given to event thread
993 mImpl->notificationManager.UpdateCompleted();
995 // The update has finished; swap the double-buffering indices
996 mSceneGraphBuffers.Swap();
1001 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1003 // Update the duration set via Stage::KeepRendering()
1004 if ( mImpl->keepRenderingSeconds > 0.0f )
1006 mImpl->keepRenderingSeconds -= elapsedSeconds;
1009 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1011 // If the rendering behavior is set to continuously render, then continue to render.
1012 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1013 // Keep updating until no messages are received and no animations are running.
1014 // If an animation has just finished, update at least once more for Discard end-actions.
1015 // No need to check for renderQueue as there is always a render after update and if that
1016 // render needs another update it will tell the adaptor to call update again
1018 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
1019 ( mImpl->keepRenderingSeconds > 0.0f ) )
1021 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1024 if ( IsAnimationRunning() ||
1025 mImpl->animationFinishedDuringUpdate )
1027 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1030 if ( mImpl->renderTaskWaiting )
1032 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1035 return keepUpdatingRequest;
1038 void UpdateManager::SetBackgroundColor( const Vector4& color )
1040 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1042 // Reserve some memory inside the render queue
1043 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1045 // Construct message in the render queue memory; note that delete should not be called on the return value
1046 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1049 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1051 mImpl->surfaceRectChanged = true;
1053 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1055 // Reserve some memory inside the render queue
1056 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1058 // Construct message in the render queue memory; note that delete should not be called on the return value
1059 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1062 void UpdateManager::KeepRendering( float durationSeconds )
1064 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1067 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1069 mImpl->renderingBehavior = renderingBehavior;
1072 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1074 const VectorBase::SizeType rootCount = mImpl->roots.Count();
1076 // Make sure we reserve the correct size for the container so that
1077 // we can save the sorted layers in the same order as the root layer
1078 mImpl->sortedLayerLists.resize( rootCount );
1080 for ( VectorBase::SizeType rootIndex = 0u; rootIndex < rootCount; rootIndex++ )
1082 Layer* root = mImpl->roots[rootIndex];
1083 if ( root == rootLayer )
1085 mImpl->sortedLayerLists[rootIndex] = layers;
1091 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1093 // note,this vector is already in depth order. It could be used as-is to
1094 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1095 for( auto&& iter : nodeDepths->nodeDepths )
1097 iter.node->SetDepthIndex( iter.sortedDepth );
1100 for( auto root : mImpl->roots )
1102 // Go through node hierarchy and rearrange siblings according to depth-index
1103 SortSiblingNodesRecursively( *root );
1107 bool UpdateManager::IsDefaultSurfaceRectChanged()
1109 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1112 mImpl->surfaceRectChanged = false;
1114 return surfaceRectChanged;
1117 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1119 mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
1122 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1124 mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
1127 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1129 // Message has ownership of Sampler while in transit from update to render
1130 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1132 // Reserve some memory inside the render queue
1133 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1135 // Construct message in the render queue memory; note that delete should not be called on the return value
1136 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1139 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1141 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1143 // Reserve some memory inside the render queue
1144 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1146 // Construct message in the render queue memory; note that delete should not be called on the return value
1147 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1150 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1152 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1154 // Reserve some memory inside the render queue
1155 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1157 // Construct message in the render queue memory; note that delete should not be called on the return value
1158 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1161 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1163 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1165 // Reserve some memory inside the render queue
1166 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1168 // Construct message in the render queue memory; note that delete should not be called on the return value
1169 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1172 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1174 // Message has ownership of format while in transit from update -> render
1175 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1177 // Reserve some memory inside the render queue
1178 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1180 // Construct message in the render queue memory; note that delete should not be called on the return value
1181 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1184 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1186 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1188 // Reserve some memory inside the render queue
1189 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1191 // Construct message in the render queue memory; note that delete should not be called on the return value
1192 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1195 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1197 // Message has ownership of format while in transit from update -> render
1198 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1200 // Reserve some memory inside the render queue
1201 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1203 // Construct message in the render queue memory; note that delete should not be called on the return value
1204 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1207 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1209 // Message has ownership of format while in transit from update -> render
1210 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1212 // Reserve some memory inside the render queue
1213 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1215 // Construct message in the render queue memory; note that delete should not be called on the return value
1216 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1219 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1221 // Message has ownership of format while in transit from update -> render
1222 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1224 // Reserve some memory inside the render queue
1225 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1227 // Construct message in the render queue memory; note that delete should not be called on the return value
1228 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1231 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1233 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1235 // Reserve some memory inside the render queue
1236 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1238 // Construct message in the render queue memory; note that delete should not be called on the return value
1239 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1242 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1244 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > DerivedType;
1246 // Reserve some memory inside the render queue
1247 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1249 // Construct message in the render queue memory; note that delete should not be called on the return value
1250 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1253 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1255 typedef IndexBufferMessage< RenderManager > DerivedType;
1257 // Reserve some memory inside the render queue
1258 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1260 // Construct message in the render queue memory; note that delete should not be called on the return value
1261 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1264 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1266 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1268 // Reserve some memory inside the render queue
1269 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1271 // Construct message in the render queue memory; note that delete should not be called on the return value
1272 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1275 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1277 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1279 // Reserve some memory inside the render queue
1280 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1282 // Construct message in the render queue memory; note that delete should not be called on the return value
1283 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1286 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1288 // Message has ownership of Texture while in transit from update -> render
1289 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1291 // Reserve some memory inside the render queue
1292 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1294 // Construct message in the render queue memory; note that delete should not be called on the return value
1295 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1298 void UpdateManager::RemoveTexture( Render::Texture* texture)
1300 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1302 // Reserve some memory inside the render queue
1303 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1305 // Construct message in the render queue memory; note that delete should not be called on the return value
1306 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1309 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1311 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1313 // Reserve some memory inside the message queue
1314 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1316 // Construct message in the message queue memory; note that delete should not be called on the return value
1317 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1320 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1322 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1324 // Reserve some memory inside the render queue
1325 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1327 // Construct message in the render queue memory; note that delete should not be called on the return value
1328 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1331 void UpdateManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
1333 typedef MessageValue1< RenderManager, OwnerPointer< Render::FrameBuffer > > DerivedType;
1335 // Reserve some memory inside the render queue
1336 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1338 // Construct message in the render queue memory; note that delete should not be called on the return value
1339 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1342 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1344 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1346 // Reserve some memory inside the render queue
1347 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1349 // Construct message in the render queue memory; note that delete should not be called on the return value
1350 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1353 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1355 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1357 // Reserve some memory inside the render queue
1358 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1360 // Construct message in the render queue memory; note that delete should not be called on the return value
1361 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1364 } // namespace SceneGraph
1366 } // namespace Internal