2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/graphics/graphics-controller.h>
25 #include <dali/public-api/common/stage.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/integration-api/debug.h>
29 #include <dali/integration-api/render-controller.h>
30 #include <dali/integration-api/graphics/graphics.h>
32 #include <dali/devel-api/common/owner-container.h>
33 #include <dali/devel-api/threading/mutex.h>
34 #include <dali/internal/common/core-impl.h>
35 #include <dali/internal/common/message.h>
36 #include <dali/internal/common/shader-data.h>
37 #include <dali/internal/event/animation/animation-playlist.h>
38 #include <dali/internal/event/common/notification-manager.h>
39 #include <dali/internal/event/common/property-notification-impl.h>
40 #include <dali/internal/event/common/property-notifier.h>
41 #include <dali/internal/event/effects/shader-factory.h>
42 #include <dali/internal/render/common/render-instruction-container.h>
43 #include <dali/internal/render/common/render-manager.h>
44 #include <dali/internal/render/queue/render-queue.h>
45 #include <dali/internal/render/shaders/scene-graph-shader.h>
46 #include <dali/internal/update/animation/scene-graph-animation.h>
47 #include <dali/internal/update/animation/scene-graph-animator.h>
48 #include <dali/internal/update/common/discard-queue.h>
49 #include <dali/internal/update/common/scene-graph-buffers.h>
50 #include <dali/internal/update/controllers/render-message-dispatcher.h>
51 #include <dali/internal/update/controllers/scene-controller-impl.h>
52 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
53 #include <dali/internal/update/graphics/graphics-algorithms.h>
54 #include <dali/internal/update/manager/render-task-processor.h>
55 #include <dali/internal/update/manager/sorted-layers.h>
56 #include <dali/internal/update/manager/transform-manager.h>
57 #include <dali/internal/update/manager/update-algorithms.h>
58 #include <dali/internal/update/manager/update-manager-debug.h>
59 #include <dali/internal/update/nodes/node.h>
60 #include <dali/internal/update/nodes/scene-graph-layer.h>
61 #include <dali/internal/update/queue/update-message-queue.h>
62 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
63 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
64 #include <dali/internal/update/render-tasks/scene-graph-render-task.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 int FRAME_COUNT_TRIGGER = 16;\
72 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
74 if ( NULL != mImpl->root )\
76 mImpl->frameCounter = 0;\
77 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
80 mImpl->frameCounter++;
82 #define SNAPSHOT_NODE_LOGGING
85 #if defined(DEBUG_ENABLED)
86 extern Debug::Filter* gRenderTaskLogFilter;
90 using namespace Dali::Integration;
91 using Dali::Internal::Update::MessageQueue;
105 * Helper to reset animate-able objects to base values
106 * @param container to iterate over
107 * @param updateBufferIndex to use
110 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
112 // Reset animatable properties to base values
113 // use reference to avoid extra copies of the iterator
114 for( auto&& iter : container )
116 iter->ResetToBaseValues( updateBufferIndex );
121 * Helper to Erase an object from OwnerContainer using discard queue
122 * @param container to remove from
123 * @param object to remove
124 * @param discardQueue to put the object to
125 * @param updateBufferIndex to use
128 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
130 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
132 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
133 for( auto&& iter : container )
135 if ( iter == object )
137 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
138 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
139 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
145 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
146 * @param[in] node The node whose hierarchy to descend
148 void SortSiblingNodesRecursively( Node& node )
150 NodeContainer& container = node.GetChildren();
151 std::sort( container.Begin(), container.End(),
152 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
154 // Descend tree and sort as well
155 for( auto&& iter : container )
157 SortSiblingNodesRecursively( *iter );
161 } // unnamed namespace
164 * Structure to contain UpdateManager internal data
166 struct UpdateManager::Impl
168 Impl( NotificationManager& notificationManager,
169 CompleteNotificationInterface& animationPlaylist,
170 PropertyNotifier& propertyNotifier,
171 DiscardQueue& discardQueue,
172 RenderController& renderController,
173 RenderManager& renderManager,
174 RenderQueue& renderQueue,
175 SceneGraphBuffers& sceneGraphBuffers,
176 RenderTaskProcessor& renderTaskProcessor,
177 Integration::Graphics::Graphics& graphics )
178 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
179 notificationManager( notificationManager ),
181 animationPlaylist( animationPlaylist ),
182 propertyNotifier( propertyNotifier ),
184 discardQueue( discardQueue ),
185 renderController( renderController ),
186 sceneController( NULL ),
187 renderManager( renderManager ),
188 renderQueue( renderQueue ),
189 renderInstructions( renderManager.GetRenderInstructionContainer() ),
190 renderTaskProcessor( renderTaskProcessor ),
191 graphics( graphics ),
192 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
193 taskList( renderMessageDispatcher ),
194 systemLevelTaskList( renderMessageDispatcher ),
196 systemLevelRoot( NULL ),
200 panGestureProcessor( NULL ),
201 messageQueue( renderController, sceneGraphBuffers ),
202 keepRenderingSeconds( 0.0f ),
203 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
205 animationFinishedDuringUpdate( false ),
206 previousUpdateScene( false ),
207 renderTaskWaiting( false ),
208 renderersAdded( false )
210 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
212 // create first 'dummy' node
218 // Disconnect render tasks from nodes, before destroying the nodes
219 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
220 for ( auto&& iter : tasks )
222 iter->SetSourceNode( NULL );
224 // ..repeat for system level RenderTasks
225 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
226 for ( auto&& iter : systemLevelTasks )
228 iter->SetSourceNode( NULL );
231 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
232 // like custom properties, which get released here
233 Vector<Node*>::Iterator iter = nodes.Begin()+1;
234 Vector<Node*>::Iterator endIter = nodes.End();
235 for(;iter!=endIter;++iter)
237 (*iter)->OnDestroy();
241 // If there is root, reset it, otherwise do nothing as rendering was never started
246 Node::Delete( root );
250 if( systemLevelRoot )
252 systemLevelRoot->OnDestroy();
254 Node::Delete( systemLevelRoot );
255 systemLevelRoot = NULL;
258 delete sceneController;
261 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
262 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
263 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
264 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
265 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
266 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
267 ShaderSaver* shaderSaver; ///< Saves shader binaries.
268 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
269 RenderController& renderController; ///< render controller
270 SceneControllerImpl* sceneController; ///< scene controller
271 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
272 RenderQueue& renderQueue; ///< Used to queue messages for the next render
273 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
274 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
275 Integration::Graphics::Graphics& graphics; ///< Graphics
277 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
279 RenderTaskList taskList; ///< The list of scene graph render-tasks
280 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
282 Layer* root; ///< The root node (root is a layer)
283 Layer* systemLevelRoot; ///< A separate root-node for system-level content
285 Vector<Node*> nodes; ///< A container of all instantiated nodes
287 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
288 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
290 OwnerContainer< Camera* > cameras; ///< A container of cameras
291 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
293 AnimationContainer animations; ///< A container of owned animations
294 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
296 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
297 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
298 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
299 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
301 MessageQueue messageQueue; ///< The messages queued from the event-thread
302 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
303 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
304 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
306 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
307 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
308 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
310 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
311 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
312 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
313 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
318 Impl( const Impl& ); ///< Undefined
319 Impl& operator=( const Impl& ); ///< Undefined
322 UpdateManager::UpdateManager( NotificationManager& notificationManager,
323 CompleteNotificationInterface& animationFinishedNotifier,
324 PropertyNotifier& propertyNotifier,
325 DiscardQueue& discardQueue,
326 RenderController& controller,
327 RenderManager& renderManager,
328 RenderQueue& renderQueue,
329 RenderTaskProcessor& renderTaskProcessor,
330 Integration::Graphics::Graphics& graphics )
331 : mImpl( new Impl( notificationManager,
332 animationFinishedNotifier,
344 UpdateManager::~UpdateManager()
346 // required due to unique_ptr to mImpl
350 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
352 DALI_ASSERT_DEBUG( layer->IsLayer() );
353 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
357 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
358 mImpl->root = layer.Release();
359 mImpl->root->CreateTransform( &mImpl->transformManager );
360 mImpl->root->SetRoot(true);
364 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
365 mImpl->systemLevelRoot = layer.Release();
366 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
367 mImpl->systemLevelRoot->SetRoot(true);
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 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 parent->ConnectChild( node );
399 void UpdateManager::DisconnectNode( Node* node )
401 Node* parent = node->GetParent();
402 DALI_ASSERT_ALWAYS( NULL != parent );
403 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
405 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
408 void UpdateManager::DestroyNode( Node* node )
410 DALI_ASSERT_ALWAYS( NULL != node );
411 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
413 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
414 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
415 for(;iter!=endIter;++iter)
419 mImpl->nodes.Erase(iter);
424 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
426 // Notify the Node about impending destruction
430 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
432 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
435 void UpdateManager::RemoveCamera( const Camera* camera )
437 // Find the camera and destroy it
438 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
441 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
443 mImpl->customObjects.PushBack( object.Release() );
446 void UpdateManager::RemoveObject( PropertyOwner* object )
448 mImpl->customObjects.EraseObject( object );
451 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
453 mImpl->animations.PushBack( animation.Release() );
456 void UpdateManager::StopAnimation( Animation* animation )
458 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
460 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
462 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
465 void UpdateManager::RemoveAnimation( Animation* animation )
467 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
469 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
471 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
474 bool UpdateManager::IsAnimationRunning() const
476 // Find any animation that isn't stopped or paused
477 for ( auto&& iter : mImpl->animations )
479 const Animation::State state = iter->GetState();
481 if (state != Animation::Stopped &&
482 state != Animation::Paused)
484 return true; // stop iteration as soon as first one is found
491 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
493 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
496 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
498 mImpl->propertyNotifications.EraseObject( propertyNotification );
501 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
503 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
504 propertyNotification->SetNotifyMode( notifyMode );
507 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
509 mImpl->shaders.PushBack( shader.Release() );
512 void UpdateManager::RemoveShader( Shader* shader )
514 // Find the shader and destroy it
515 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
518 void UpdateManager::SetShaderProgram( Shader* shader,
519 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
525 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
527 // Reserve some memory inside the render queue
528 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
530 // Construct message in the render queue memory; note that delete should not be called on the return value
531 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
535 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
537 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
538 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
540 // lock as update might be sending previously compiled shaders to event thread
541 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
542 mImpl->renderCompiledShaders.push_back( shaderData );
546 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
548 mImpl->shaderSaver = &upstream;
551 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
553 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
554 mImpl->renderers.PushBack( renderer.Release() );
555 mImpl->renderersAdded = true;
558 void UpdateManager::RemoveRenderer( Renderer* renderer )
560 // Find the renderer and destroy it
561 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
562 // Need to remove the render object as well
563 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
566 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
568 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
570 mImpl->panGestureProcessor = panGestureProcessor;
573 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
575 mImpl->textureSets.PushBack( textureSet.Release() );
578 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
580 mImpl->textureSets.EraseObject( textureSet );
583 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
587 // copy the list, this is only likely to happen once in application life cycle
588 return &(mImpl->taskList);
592 // copy the list, this is only likely to happen once in application life cycle
593 return &(mImpl->systemLevelTaskList);
597 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
599 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
602 void UpdateManager::EventProcessingStarted()
604 mImpl->messageQueue.EventProcessingStarted();
607 bool UpdateManager::FlushQueue()
609 return mImpl->messageQueue.FlushQueue();
612 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
614 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
615 mImpl->animationFinishedDuringUpdate = false;
617 // Animated properties have to be reset to their original value each frame
619 // Reset root properties
622 mImpl->root->ResetToBaseValues( bufferIndex );
624 if ( mImpl->systemLevelRoot )
626 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
629 // Reset all the nodes
630 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
631 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
632 for( ;iter != endIter; ++iter )
634 (*iter)->ResetToBaseValues( bufferIndex );
637 // Reset system-level render-task list properties to base values
638 ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
640 // Reset render-task list properties to base values.
641 ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
643 // Reset custom object properties to base values
644 ResetToBaseValues( mImpl->customObjects, bufferIndex );
646 // Reset animatable renderer properties to base values
647 ResetToBaseValues( mImpl->renderers, bufferIndex );
649 // Reset animatable shader properties to base values
650 ResetToBaseValues( mImpl->shaders, bufferIndex );
653 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
655 bool gestureUpdated( false );
657 if( mImpl->panGestureProcessor )
659 // gesture processor only supports default properties
660 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
661 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
664 return gestureUpdated;
667 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
669 AnimationContainer &animations = mImpl->animations;
670 AnimationIter iter = animations.Begin();
671 bool animationLooped = false;
673 while ( iter != animations.End() )
675 Animation* animation = *iter;
676 bool finished = false;
678 bool progressMarkerReached = false;
679 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
681 if ( progressMarkerReached )
683 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
686 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
687 animationLooped = animationLooped || looped;
689 // Remove animations that had been destroyed but were still waiting for an update
690 if (animation->GetState() == Animation::Destroyed)
692 iter = animations.Erase(iter);
700 // queue the notification on finished or looped (to update loop count)
701 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
703 // The application should be notified by NotificationManager, in another thread
704 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
708 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
710 //Constrain custom objects (in construction order)
711 for ( auto&& object : mImpl->customObjects )
713 ConstrainPropertyOwner( *object, bufferIndex );
717 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
719 // Constrain system-level render-tasks
720 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
721 for ( auto&& task : systemLevelTasks )
723 ConstrainPropertyOwner( *task, bufferIndex );
726 // Constrain render-tasks
727 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
728 for ( auto&& task : tasks )
730 ConstrainPropertyOwner( *task, bufferIndex );
734 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
736 // constrain shaders... (in construction order)
737 for ( auto&& shader : mImpl->shaders )
739 ConstrainPropertyOwner( *shader, bufferIndex );
743 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
745 for( auto&& notification : mImpl->propertyNotifications )
747 bool valid = notification->Check( bufferIndex );
750 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
755 void UpdateManager::ForwardCompiledShadersToEventThread()
757 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
758 if( mImpl->shaderSaver )
760 // lock and swap the queues
762 // render might be attempting to send us more binaries at the same time
763 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
764 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
767 if( mImpl->updateCompiledShaders.size() > 0 )
769 ShaderSaver& factory = *mImpl->shaderSaver;
770 for( auto&& shader : mImpl->updateCompiledShaders )
772 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
774 // we don't need them in update anymore
775 mImpl->updateCompiledShaders.clear();
780 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
782 const unsigned int rendererCount = mImpl->renderers.Count();
783 for( unsigned int i = 0; i < rendererCount; ++i )
786 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
788 mImpl->renderers[i]->PrepareRender( bufferIndex );
792 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
794 mImpl->nodeDirtyFlags = NothingFlag;
801 // Prepare resources, update shaders, for each node
802 // And add the renderers to the sorted layers. Start from root, which is also a layer
803 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
805 mImpl->renderQueue );
807 if ( mImpl->systemLevelRoot )
809 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
811 mImpl->renderQueue );
815 unsigned int UpdateManager::Update( float elapsedSeconds,
816 unsigned int lastVSyncTimeMilliseconds,
817 unsigned int 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
836 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
837 // values if the scene was updated in the previous frame.
838 if( updateScene || mImpl->previousUpdateScene )
840 //Reset properties from the previous update
841 ResetProperties( bufferIndex );
842 mImpl->transformManager.ResetToBaseValue();
845 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
846 // between calling IsSceneUpdateRequired() above and here, so updateScene should
848 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
850 //Forward compiled shader programs to event thread for saving
851 ForwardCompiledShadersToEventThread();
853 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
854 // renderer lists if the scene was updated in the previous frame.
855 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
856 if( updateScene || mImpl->previousUpdateScene )
859 Animate( bufferIndex, elapsedSeconds );
861 //Constraint custom objects
862 ConstrainCustomObjects( bufferIndex );
864 //Clear the lists of renderers from the previous update
865 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
867 mImpl->sortedLayers[i]->ClearRenderables();
870 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
872 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
875 //Update node hierarchy, apply constraints and perform sorting / culling.
876 //This will populate each Layer with a list of renderers which are ready.
877 UpdateNodes( bufferIndex );
879 //Apply constraints to RenderTasks, shaders
880 ConstrainRenderTasks( bufferIndex );
881 ConstrainShaders( bufferIndex );
883 //Update renderers and apply constraints
884 UpdateRenderers( bufferIndex );
886 //Update the trnasformations of all the nodes
887 mImpl->transformManager.Update();
889 //Process Property Notifications
890 ProcessPropertyNotifications( bufferIndex );
893 for( auto&& cameraIterator : mImpl->cameras )
895 cameraIterator->Update( bufferIndex );
898 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
899 //reset the update buffer index and make sure there is enough room in the instruction container
900 if( mImpl->renderersAdded )
902 mImpl->renderInstructions.ResetAndReserve(bufferIndex,
903 mImpl->taskList.GetTasks().Count() +
904 mImpl->systemLevelTaskList.GetTasks().Count());
906 if ( NULL != mImpl->root )
908 mImpl->renderTaskProcessor.Process( bufferIndex,
912 mImpl->renderInstructions,
916 // Process the system-level RenderTasks last
917 if ( NULL != mImpl->systemLevelRoot )
919 mImpl->renderTaskProcessor.Process( bufferIndex,
920 mImpl->systemLevelTaskList,
921 *mImpl->systemLevelRoot,
922 mImpl->systemLevelSortedLayers,
923 mImpl->renderInstructions,
928 // generate graphics objects
930 SubmitRenderInstructions( mImpl->graphics.GetController(), mImpl->renderInstructions, bufferIndex );
934 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
935 bool doRenderOnceNotify = false;
936 mImpl->renderTaskWaiting = false;
937 for ( auto&& renderTask : mImpl->taskList.GetTasks() )
939 renderTask->UpdateState();
941 if( renderTask->IsWaitingToRender() &&
942 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
944 mImpl->renderTaskWaiting = true; // keep update/render threads alive
947 if( renderTask->HasRendered() )
949 doRenderOnceNotify = true;
953 if( doRenderOnceNotify )
955 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
956 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
959 // Macro is undefined in release build.
960 SNAPSHOT_NODE_LOGGING;
962 // A ResetProperties() may be required in the next frame
963 mImpl->previousUpdateScene = updateScene;
965 // Check whether further updates are required
966 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
968 // tell the update manager that we're done so the queue can be given to event thread
969 mImpl->notificationManager.UpdateCompleted();
971 // The update has finished; swap the double-buffering indices
972 mSceneGraphBuffers.Swap();
977 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
979 // Update the duration set via Stage::KeepRendering()
980 if ( mImpl->keepRenderingSeconds > 0.0f )
982 mImpl->keepRenderingSeconds -= elapsedSeconds;
985 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
987 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
988 // Keep updating until no messages are received and no animations are running.
989 // If an animation has just finished, update at least once more for Discard end-actions.
990 // No need to check for renderQueue as there is always a render after update and if that
991 // render needs another update it will tell the adaptor to call update again
993 if ( mImpl->keepRenderingSeconds > 0.0f )
995 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
998 if ( IsAnimationRunning() ||
999 mImpl->animationFinishedDuringUpdate )
1001 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1004 if ( mImpl->renderTaskWaiting )
1006 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1009 return keepUpdatingRequest;
1012 void UpdateManager::SetBackgroundColor( const Vector4& color )
1014 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1016 // Reserve some memory inside the render queue
1017 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1019 // Construct message in the render queue memory; note that delete should not be called on the return value
1020 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1023 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1025 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1027 // Reserve some memory inside the render queue
1028 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1030 // Construct message in the render queue memory; note that delete should not be called on the return value
1031 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1034 void UpdateManager::KeepRendering( float durationSeconds )
1036 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1039 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1043 // just copy the vector of pointers
1044 mImpl->sortedLayers = layers;
1048 mImpl->systemLevelSortedLayers = layers;
1052 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1054 // note,this vector is already in depth order. It could be used as-is to
1055 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1056 for( auto&& iter : nodeDepths->nodeDepths )
1058 iter.node->SetDepthIndex( iter.sortedDepth );
1061 // Go through node hierarchy and rearrange siblings according to depth-index
1062 SortSiblingNodesRecursively( *( mImpl->root ) );
1065 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1067 // Message has ownership of Sampler while in transit from update to render
1068 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1070 // Reserve some memory inside the render queue
1071 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1073 // Construct message in the render queue memory; note that delete should not be called on the return value
1074 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1077 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1079 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1081 // Reserve some memory inside the render queue
1082 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1084 // Construct message in the render queue memory; note that delete should not be called on the return value
1085 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1088 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1090 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1092 // Reserve some memory inside the render queue
1093 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1095 // Construct message in the render queue memory; note that delete should not be called on the return value
1096 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1099 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1101 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1103 // Reserve some memory inside the render queue
1104 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1106 // Construct message in the render queue memory; note that delete should not be called on the return value
1107 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1110 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1112 // Message has ownership of format while in transit from update -> render
1113 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1115 // Reserve some memory inside the render queue
1116 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1118 // Construct message in the render queue memory; note that delete should not be called on the return value
1119 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1122 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1124 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1126 // Reserve some memory inside the render queue
1127 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1129 // Construct message in the render queue memory; note that delete should not be called on the return value
1130 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1133 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1135 // Message has ownership of format while in transit from update -> render
1136 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1138 // Reserve some memory inside the render queue
1139 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1141 // Construct message in the render queue memory; note that delete should not be called on the return value
1142 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1145 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
1147 // Message has ownership of format while in transit from update -> render
1148 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1150 // Reserve some memory inside the render queue
1151 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1153 // Construct message in the render queue memory; note that delete should not be called on the return value
1154 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1157 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1159 // Message has ownership of format while in transit from update -> render
1160 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1162 // Reserve some memory inside the render queue
1163 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1165 // Construct message in the render queue memory; note that delete should not be called on the return value
1166 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1169 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1171 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1173 // Reserve some memory inside the render queue
1174 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1176 // Construct message in the render queue memory; note that delete should not be called on the return value
1177 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1180 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1182 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1184 // Reserve some memory inside the render queue
1185 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1187 // Construct message in the render queue memory; note that delete should not be called on the return value
1188 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1191 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1193 typedef IndexBufferMessage< RenderManager > DerivedType;
1195 // Reserve some memory inside the render queue
1196 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1198 // Construct message in the render queue memory; note that delete should not be called on the return value
1199 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1202 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1204 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1206 // Reserve some memory inside the render queue
1207 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1209 // Construct message in the render queue memory; note that delete should not be called on the return value
1210 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1213 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1215 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1217 // Reserve some memory inside the render queue
1218 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1220 // Construct message in the render queue memory; note that delete should not be called on the return value
1221 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1224 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1226 // Message has ownership of Texture while in transit from update -> render
1227 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1229 // Reserve some memory inside the render queue
1230 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1232 // Construct message in the render queue memory; note that delete should not be called on the return value
1233 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1236 void UpdateManager::RemoveTexture( Render::Texture* texture)
1238 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1240 // Reserve some memory inside the render queue
1241 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1243 // Construct message in the render queue memory; note that delete should not be called on the return value
1244 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1247 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1249 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1251 // Reserve some memory inside the message queue
1252 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1254 // Construct message in the message queue memory; note that delete should not be called on the return value
1255 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1258 void UpdateManager::UploadTextureV2( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1260 //fixme: AB: This is temporary solution to create a texture object on the Graphics API side
1261 //fixme: using controller directly in the update thread
1262 auto& controller = mImpl->graphics.GetController();
1264 // function returns an opaque object which has to be stored in the texture implementation
1265 auto textureId = controller.CreateTextureRGBA32( pixelData->GetBuffer(), pixelData->GetBufferSize(),
1266 pixelData->GetWidth(), pixelData->GetHeight());
1268 // AB: workaround, assigning instantly texture Id to the render object
1269 texture->SetId( textureId );
1271 std::cout << textureId << std::endl;
1274 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1276 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1278 // Reserve some memory inside the render queue
1279 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1281 // Construct message in the render queue memory; note that delete should not be called on the return value
1282 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1285 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1287 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1289 // Reserve some memory inside the render queue
1290 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1292 // Construct message in the render queue memory; note that delete should not be called on the return value
1293 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1296 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1298 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1300 // Reserve some memory inside the render queue
1301 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1303 // Construct message in the render queue memory; note that delete should not be called on the return value
1304 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1307 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1309 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1311 // Reserve some memory inside the render queue
1312 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1314 // Construct message in the render queue memory; note that delete should not be called on the return value
1315 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1318 } // namespace SceneGraph
1320 } // namespace Internal