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 ),
197 nodeDisconnected( false )
199 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
201 // create first 'dummy' node
207 // Disconnect render tasks from nodes, before destroying the nodes
208 for( auto taskList : taskLists )
210 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
211 for ( auto&& task : tasks )
213 task->SetSourceNode( NULL );
217 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
218 // like custom properties, which get released here
219 Vector<Node*>::Iterator iter = nodes.Begin()+1;
220 Vector<Node*>::Iterator endIter = nodes.End();
221 for(;iter!=endIter;++iter)
223 (*iter)->OnDestroy();
227 for( auto root : roots )
233 delete sceneController;
237 * Lazy init for FrameCallbackProcessor.
238 * @param[in] updateManager A reference to the update-manager
240 FrameCallbackProcessor& GetFrameCallbackProcessor( UpdateManager& updateManager )
242 if( ! frameCallbackProcessor )
244 frameCallbackProcessor = new FrameCallbackProcessor( updateManager, transformManager );
246 return *frameCallbackProcessor;
249 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
250 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
251 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
252 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
253 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
254 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
255 ShaderSaver* shaderSaver; ///< Saves shader binaries.
256 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
257 RenderController& renderController; ///< render controller
258 SceneControllerImpl* sceneController; ///< scene controller
259 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
260 RenderQueue& renderQueue; ///< Used to queue messages for the next render
261 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
262 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
264 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
266 OwnerContainer<RenderTaskList*> taskLists; ///< A container of scene graph render task lists
268 Vector<Layer*> roots; ///< A container of root nodes (root is a layer). The layers are not stored in the node memory pool.
270 Vector<Node*> nodes; ///< A container of all instantiated nodes
272 std::vector<SortedLayerPointers> sortedLayerLists; ///< A container of lists of Layer pointers sorted by depth (one list of sorted layers per root)
274 OwnerContainer< Camera* > cameras; ///< A container of cameras
275 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
277 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
278 OwnerContainer< Animation* > animations; ///< A container of owned animations
279 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
280 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
281 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
282 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
283 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
285 MessageQueue messageQueue; ///< The messages queued from the event-thread
286 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
287 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
288 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
290 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
292 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
293 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
294 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
296 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
298 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
299 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
300 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
301 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
302 bool surfaceRectChanged; ///< True if the default surface rect is changed
303 bool nodeDisconnected; ///< True if a node is disconnected in the current update
307 Impl( const Impl& ); ///< Undefined
308 Impl& operator=( const Impl& ); ///< Undefined
311 UpdateManager::UpdateManager( NotificationManager& notificationManager,
312 CompleteNotificationInterface& animationFinishedNotifier,
313 PropertyNotifier& propertyNotifier,
314 DiscardQueue& discardQueue,
315 RenderController& controller,
316 RenderManager& renderManager,
317 RenderQueue& renderQueue,
318 RenderTaskProcessor& renderTaskProcessor )
321 mImpl = new Impl( notificationManager,
322 animationFinishedNotifier,
329 renderTaskProcessor );
333 UpdateManager::~UpdateManager()
338 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
340 DALI_ASSERT_DEBUG( layer->IsLayer() );
341 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
343 Layer* rootLayer = layer.Release();
345 DALI_ASSERT_DEBUG( std::find( mImpl->roots.begin(), mImpl->roots.end(), rootLayer ) == mImpl->roots.end() && "Root Node already installed" );
347 rootLayer->CreateTransform( &mImpl->transformManager );
348 rootLayer->SetRoot(true);
349 mImpl->roots.PushBack( rootLayer );
352 void UpdateManager::UninstallRoot( Layer* layer )
354 DALI_ASSERT_DEBUG( layer->IsLayer() );
355 DALI_ASSERT_DEBUG( layer->GetParent() == NULL );
357 for ( auto&& iter : mImpl->roots )
359 if( ( *iter ) == layer )
361 mImpl->roots.Erase( &iter );
366 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), layer );
368 // Notify the layer about impending destruction
372 void UpdateManager::AddNode( OwnerPointer<Node>& node )
374 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
376 // Nodes must be sorted by pointer
377 Node* rawNode = node.Release();
378 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddNode\n", rawNode );
380 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
381 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
383 if( rawNode > (*iter) )
385 mImpl->nodes.Insert((iter+1), rawNode );
386 rawNode->CreateTransform( &mImpl->transformManager );
392 void UpdateManager::ConnectNode( Node* parent, Node* node )
394 DALI_ASSERT_ALWAYS( NULL != parent );
395 DALI_ASSERT_ALWAYS( NULL != node );
396 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
398 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] ConnectNode\n", node );
400 parent->ConnectChild( node );
402 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
403 if( mImpl->frameCallbackProcessor )
405 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
409 void UpdateManager::DisconnectNode( Node* node )
411 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DisconnectNode\n", node );
413 mImpl->nodeDisconnected = true;
415 Node* parent = node->GetParent();
416 DALI_ASSERT_ALWAYS( NULL != parent );
417 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
419 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
421 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
422 if( mImpl->frameCallbackProcessor )
424 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
428 void UpdateManager::DestroyNode( Node* node )
430 DALI_ASSERT_ALWAYS( NULL != node );
431 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
433 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DestroyNode\n", node );
435 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
436 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
437 for(;iter!=endIter;++iter)
441 mImpl->nodes.Erase(iter);
446 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
448 // Notify the Node about impending destruction
452 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
454 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
457 void UpdateManager::RemoveCamera( Camera* camera )
459 // Find the camera and destroy it
460 EraseUsingDiscardQueue( mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
463 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
465 mImpl->customObjects.PushBack( object.Release() );
468 void UpdateManager::RemoveObject( PropertyOwner* object )
470 mImpl->customObjects.EraseObject( object );
473 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
475 RenderTaskList* taskListPointer = taskList.Release();
476 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
477 mImpl->taskLists.PushBack( taskListPointer );
480 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
482 mImpl->taskLists.EraseObject( taskList );
485 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
487 mImpl->animations.PushBack( animation.Release() );
490 void UpdateManager::StopAnimation( Animation* animation )
492 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
494 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
496 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
499 void UpdateManager::RemoveAnimation( Animation* animation )
501 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
503 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
505 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
508 bool UpdateManager::IsAnimationRunning() const
510 // Find any animation that isn't stopped or paused
511 for ( auto&& iter : mImpl->animations )
513 const Animation::State state = iter->GetState();
515 if (state != Animation::Stopped &&
516 state != Animation::Paused)
518 return true; // stop iteration as soon as first one is found
525 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
527 propertyResetter->Initialize();
528 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
531 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
533 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
536 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
538 mImpl->propertyNotifications.EraseObject( propertyNotification );
541 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
543 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
544 propertyNotification->SetNotifyMode( notifyMode );
547 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
549 mImpl->shaders.PushBack( shader.Release() );
552 void UpdateManager::RemoveShader( Shader* shader )
554 // Find the shader and destroy it
555 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
558 void UpdateManager::SetShaderProgram( Shader* shader,
559 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
564 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
566 // Reserve some memory inside the render queue
567 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
569 // Construct message in the render queue memory; note that delete should not be called on the return value
570 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
574 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
576 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
577 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
579 // lock as update might be sending previously compiled shaders to event thread
580 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
581 mImpl->renderCompiledShaders.push_back( shaderData );
585 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
587 mImpl->shaderSaver = &upstream;
590 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
592 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer.Get() );
594 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
595 mImpl->renderers.PushBack( renderer.Release() );
596 mImpl->renderersAdded = true;
599 void UpdateManager::RemoveRenderer( Renderer* renderer )
601 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer );
603 // Find the renderer and destroy it
604 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
605 // Need to remove the render object as well
606 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
609 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
611 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
613 mImpl->panGestureProcessor = panGestureProcessor;
616 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
618 mImpl->textureSets.PushBack( textureSet.Release() );
621 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
623 mImpl->textureSets.EraseObject( textureSet );
626 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
628 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
631 void UpdateManager::EventProcessingStarted()
633 mImpl->messageQueue.EventProcessingStarted();
636 bool UpdateManager::FlushQueue()
638 return mImpl->messageQueue.FlushQueue();
641 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
643 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
644 mImpl->animationFinishedDuringUpdate = false;
646 // Reset all animating / constrained properties
647 std::vector<PropertyResetterBase*>toDelete;
648 for( auto&& element : mImpl->propertyResetters )
650 element->ResetToBaseValue( bufferIndex );
651 if( element->IsFinished() )
653 toDelete.push_back( element );
657 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
658 for( auto&& elementPtr : toDelete )
660 mImpl->propertyResetters.EraseObject( elementPtr );
663 // Clear node dirty flags
664 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
665 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
666 for( ;iter != endIter; ++iter )
668 (*iter)->ResetDirtyFlags( bufferIndex );
672 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
674 bool gestureUpdated( false );
676 if( mImpl->panGestureProcessor )
678 // gesture processor only supports default properties
679 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
680 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
683 return gestureUpdated;
686 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
688 auto&& iter = mImpl->animations.Begin();
689 bool animationLooped = false;
691 while ( iter != mImpl->animations.End() )
693 Animation* animation = *iter;
694 bool finished = false;
696 bool progressMarkerReached = false;
697 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
699 if ( progressMarkerReached )
701 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
704 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
705 animationLooped = animationLooped || looped;
707 // Remove animations that had been destroyed but were still waiting for an update
708 if (animation->GetState() == Animation::Destroyed)
710 iter = mImpl->animations.Erase(iter);
718 // queue the notification on finished or looped (to update loop count)
719 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
721 // The application should be notified by NotificationManager, in another thread
722 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
726 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
728 //Constrain custom objects (in construction order)
729 for ( auto&& object : mImpl->customObjects )
731 ConstrainPropertyOwner( *object, bufferIndex );
735 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
737 // Constrain render-tasks
738 for( auto taskList : mImpl->taskLists )
740 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
741 for ( auto&& task : tasks )
743 ConstrainPropertyOwner( *task, bufferIndex );
748 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
750 // constrain shaders... (in construction order)
751 for ( auto&& shader : mImpl->shaders )
753 ConstrainPropertyOwner( *shader, bufferIndex );
757 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
759 for( auto&& notification : mImpl->propertyNotifications )
761 bool valid = notification->Check( bufferIndex );
764 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
769 void UpdateManager::ForwardCompiledShadersToEventThread()
771 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
772 if( mImpl->shaderSaver )
774 // lock and swap the queues
776 // render might be attempting to send us more binaries at the same time
777 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
778 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
781 if( mImpl->updateCompiledShaders.size() > 0 )
783 ShaderSaver& factory = *mImpl->shaderSaver;
784 for( auto&& shader : mImpl->updateCompiledShaders )
786 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
788 // we don't need them in update anymore
789 mImpl->updateCompiledShaders.clear();
794 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
796 for( auto&& renderer : mImpl->renderers )
799 ConstrainPropertyOwner( *renderer, bufferIndex );
801 renderer->PrepareRender( bufferIndex );
805 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
807 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
809 for( auto&& rootLayer : mImpl->roots )
811 // Prepare resources, update shaders, for each node
812 // And add the renderers to the sorted layers. Start from root, which is also a layer
813 mImpl->nodeDirtyFlags |= UpdateNodeTree( *rootLayer,
815 mImpl->renderQueue );
819 uint32_t UpdateManager::Update( float elapsedSeconds,
820 uint32_t lastVSyncTimeMilliseconds,
821 uint32_t nextVSyncTimeMilliseconds,
822 bool renderToFboEnabled,
823 bool isRenderingToFbo )
825 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
827 //Clear nodes/resources which were previously discarded
828 mImpl->discardQueue.Clear( bufferIndex );
830 //Process Touches & Gestures
831 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
833 bool updateScene = // The scene-graph requires an update if..
834 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
835 IsAnimationRunning() || // ..at least one animation is running OR
836 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
837 gestureUpdated; // ..a gesture property was updated
839 bool keepRendererRendering = false;
841 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
842 // values if the scene was updated in the previous frame.
843 if( updateScene || mImpl->previousUpdateScene )
845 //Reset properties from the previous update
846 ResetProperties( bufferIndex );
847 mImpl->transformManager.ResetToBaseValue();
850 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
851 // between calling IsSceneUpdateRequired() above and here, so updateScene should
853 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
855 //Forward compiled shader programs to event thread for saving
856 ForwardCompiledShadersToEventThread();
858 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
859 // renderer lists if the scene was updated in the previous frame.
860 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
861 if( updateScene || mImpl->previousUpdateScene )
864 Animate( bufferIndex, elapsedSeconds );
866 //Constraint custom objects
867 ConstrainCustomObjects( bufferIndex );
869 //Clear the lists of renderers from the previous update
870 for( auto sortedLayers : mImpl->sortedLayerLists )
872 for( auto&& layer : sortedLayers )
874 layer->ClearRenderables();
878 // Call the frame-callback-processor if set
879 if( mImpl->frameCallbackProcessor )
881 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
884 //Update node hierarchy, apply constraints and perform sorting / culling.
885 //This will populate each Layer with a list of renderers which are ready.
886 UpdateNodes( bufferIndex );
888 //Apply constraints to RenderTasks, shaders
889 ConstrainRenderTasks( bufferIndex );
890 ConstrainShaders( bufferIndex );
892 //Update renderers and apply constraints
893 UpdateRenderers( bufferIndex );
895 //Update the transformations of all the nodes
896 mImpl->transformManager.Update();
898 //Process Property Notifications
899 ProcessPropertyNotifications( bufferIndex );
902 for( auto&& cameraIterator : mImpl->cameras )
904 cameraIterator->Update( bufferIndex );
907 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
908 //reset the update buffer index and make sure there is enough room in the instruction container
909 if( mImpl->renderersAdded )
911 // Calculate how many render tasks we have in total
912 VectorBase::SizeType numberOfRenderTasks = 0;
914 const VectorBase::SizeType taskListCount = mImpl->taskLists.Count();
915 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
917 numberOfRenderTasks += mImpl->taskLists[index]->GetTasks().Count();
920 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
921 static_cast<uint32_t>( numberOfRenderTasks ) );
923 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
925 if ( NULL != mImpl->roots[index] )
927 keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
928 *mImpl->taskLists[index],
929 *mImpl->roots[index],
930 mImpl->sortedLayerLists[index],
931 mImpl->renderInstructions,
937 DALI_LOG_INFO( gLogFilter, Debug::General,
938 "Update: numberOfRenderTasks(%d), taskListCount(%d), Render Instructions(%d)\n",
939 numberOfRenderTasks, taskListCount, mImpl->renderInstructions.Count( bufferIndex ) );
941 // If a node has been disconnected in this update and we do not have any instructions to send, then generate a dummy instruction to force another render
942 if( mImpl->nodeDisconnected && ( mImpl->renderInstructions.Count( bufferIndex ) == 0 ) )
944 DALI_LOG_INFO( gLogFilter, Debug::General, "Node disconnected, creating dummy instruction\n" );
945 mImpl->renderInstructions.GetNextInstruction( bufferIndex ); // This creates and adds an empty instruction. We do not need to modify it.
948 mImpl->nodeDisconnected = false;
952 for( auto taskList : mImpl->taskLists )
954 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
956 // check the countdown and notify
957 bool doRenderOnceNotify = false;
958 mImpl->renderTaskWaiting = false;
959 for ( auto&& renderTask : tasks )
961 renderTask->UpdateState();
963 if( renderTask->IsWaitingToRender() &&
964 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
966 mImpl->renderTaskWaiting = true; // keep update/render threads alive
969 if( renderTask->HasRendered() )
971 doRenderOnceNotify = true;
975 if( doRenderOnceNotify )
977 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
978 mImpl->notificationManager.QueueCompleteNotification( taskList->GetCompleteNotificationInterface() );
982 // Macro is undefined in release build.
983 SNAPSHOT_NODE_LOGGING;
985 // A ResetProperties() may be required in the next frame
986 mImpl->previousUpdateScene = updateScene;
988 // Check whether further updates are required
989 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
991 if( keepRendererRendering )
993 keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
996 // tell the update manager that we're done so the queue can be given to event thread
997 mImpl->notificationManager.UpdateCompleted();
999 // The update has finished; swap the double-buffering indices
1000 mSceneGraphBuffers.Swap();
1002 return keepUpdating;
1005 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1007 // Update the duration set via Stage::KeepRendering()
1008 if ( mImpl->keepRenderingSeconds > 0.0f )
1010 mImpl->keepRenderingSeconds -= elapsedSeconds;
1013 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1015 // If the rendering behavior is set to continuously render, then continue to render.
1016 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1017 // Keep updating until no messages are received and no animations are running.
1018 // If an animation has just finished, update at least once more for Discard end-actions.
1019 // No need to check for renderQueue as there is always a render after update and if that
1020 // render needs another update it will tell the adaptor to call update again
1022 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
1023 ( mImpl->keepRenderingSeconds > 0.0f ) )
1025 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1028 if ( IsAnimationRunning() ||
1029 mImpl->animationFinishedDuringUpdate )
1031 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1034 if ( mImpl->renderTaskWaiting )
1036 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1039 return keepUpdatingRequest;
1042 void UpdateManager::SetBackgroundColor( const Vector4& color )
1044 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1046 // Reserve some memory inside the render queue
1047 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1049 // Construct message in the render queue memory; note that delete should not be called on the return value
1050 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1053 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1055 mImpl->surfaceRectChanged = true;
1057 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1059 // Reserve some memory inside the render queue
1060 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1062 // Construct message in the render queue memory; note that delete should not be called on the return value
1063 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1066 void UpdateManager::KeepRendering( float durationSeconds )
1068 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1071 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1073 mImpl->renderingBehavior = renderingBehavior;
1076 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1078 const VectorBase::SizeType rootCount = mImpl->roots.Count();
1080 // Make sure we reserve the correct size for the container so that
1081 // we can save the sorted layers in the same order as the root layer
1082 mImpl->sortedLayerLists.resize( rootCount );
1084 for ( VectorBase::SizeType rootIndex = 0u; rootIndex < rootCount; rootIndex++ )
1086 Layer* root = mImpl->roots[rootIndex];
1087 if ( root == rootLayer )
1089 mImpl->sortedLayerLists[rootIndex] = layers;
1095 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1097 // note,this vector is already in depth order. It could be used as-is to
1098 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1099 for( auto&& iter : nodeDepths->nodeDepths )
1101 iter.node->SetDepthIndex( iter.sortedDepth );
1104 for( auto root : mImpl->roots )
1106 // Go through node hierarchy and rearrange siblings according to depth-index
1107 SortSiblingNodesRecursively( *root );
1111 bool UpdateManager::IsDefaultSurfaceRectChanged()
1113 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1116 mImpl->surfaceRectChanged = false;
1118 return surfaceRectChanged;
1121 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1123 mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
1126 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1128 mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
1131 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1133 // Message has ownership of Sampler while in transit from update to render
1134 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1136 // Reserve some memory inside the render queue
1137 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1139 // Construct message in the render queue memory; note that delete should not be called on the return value
1140 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1143 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1145 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1147 // Reserve some memory inside the render queue
1148 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1150 // Construct message in the render queue memory; note that delete should not be called on the return value
1151 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1154 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1156 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1158 // Reserve some memory inside the render queue
1159 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1161 // Construct message in the render queue memory; note that delete should not be called on the return value
1162 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1165 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1167 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1169 // Reserve some memory inside the render queue
1170 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1172 // Construct message in the render queue memory; note that delete should not be called on the return value
1173 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1176 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1178 // Message has ownership of format while in transit from update -> render
1179 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1181 // Reserve some memory inside the render queue
1182 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1184 // Construct message in the render queue memory; note that delete should not be called on the return value
1185 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1188 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1190 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1192 // Reserve some memory inside the render queue
1193 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1195 // Construct message in the render queue memory; note that delete should not be called on the return value
1196 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1199 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1201 // Message has ownership of format while in transit from update -> render
1202 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1204 // Reserve some memory inside the render queue
1205 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1207 // Construct message in the render queue memory; note that delete should not be called on the return value
1208 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1211 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1213 // Message has ownership of format while in transit from update -> render
1214 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1216 // Reserve some memory inside the render queue
1217 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1219 // Construct message in the render queue memory; note that delete should not be called on the return value
1220 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1223 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1225 // Message has ownership of format while in transit from update -> render
1226 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1228 // Reserve some memory inside the render queue
1229 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1231 // Construct message in the render queue memory; note that delete should not be called on the return value
1232 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1235 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1237 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1239 // Reserve some memory inside the render queue
1240 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1242 // Construct message in the render queue memory; note that delete should not be called on the return value
1243 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1246 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1248 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > DerivedType;
1250 // Reserve some memory inside the render queue
1251 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1253 // Construct message in the render queue memory; note that delete should not be called on the return value
1254 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1257 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1259 typedef IndexBufferMessage< RenderManager > DerivedType;
1261 // Reserve some memory inside the render queue
1262 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1264 // Construct message in the render queue memory; note that delete should not be called on the return value
1265 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1268 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1270 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1272 // Reserve some memory inside the render queue
1273 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1275 // Construct message in the render queue memory; note that delete should not be called on the return value
1276 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1279 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1281 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1283 // Reserve some memory inside the render queue
1284 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1286 // Construct message in the render queue memory; note that delete should not be called on the return value
1287 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1290 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1292 // Message has ownership of Texture while in transit from update -> render
1293 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1295 // Reserve some memory inside the render queue
1296 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1298 // Construct message in the render queue memory; note that delete should not be called on the return value
1299 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1302 void UpdateManager::RemoveTexture( Render::Texture* texture)
1304 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1306 // Reserve some memory inside the render queue
1307 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1309 // Construct message in the render queue memory; note that delete should not be called on the return value
1310 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1313 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1315 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1317 // Reserve some memory inside the message queue
1318 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1320 // Construct message in the message queue memory; note that delete should not be called on the return value
1321 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1324 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1326 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1328 // Reserve some memory inside the render queue
1329 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1331 // Construct message in the render queue memory; note that delete should not be called on the return value
1332 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1335 void UpdateManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
1337 typedef MessageValue1< RenderManager, OwnerPointer< Render::FrameBuffer > > DerivedType;
1339 // Reserve some memory inside the render queue
1340 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1342 // Construct message in the render queue memory; note that delete should not be called on the return value
1343 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1346 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1348 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1350 // Reserve some memory inside the render queue
1351 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1353 // Construct message in the render queue memory; note that delete should not be called on the return value
1354 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1357 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1359 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1361 // Reserve some memory inside the render queue
1362 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1364 // Construct message in the render queue memory; note that delete should not be called on the return value
1365 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1368 } // namespace SceneGraph
1370 } // namespace Internal