2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/owner-container.h>
24 #include <dali/devel-api/threading/mutex.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/render-controller.h>
28 #include <dali/internal/common/shader-data.h>
29 #include <dali/integration-api/debug.h>
31 #include <dali/internal/common/core-impl.h>
32 #include <dali/internal/common/message.h>
34 #include <dali/internal/event/common/notification-manager.h>
35 #include <dali/internal/event/common/property-notification-impl.h>
36 #include <dali/internal/event/common/property-notifier.h>
37 #include <dali/internal/event/effects/shader-factory.h>
38 #include <dali/internal/event/animation/animation-playlist.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/scene-graph-buffers.h>
44 #include <dali/internal/update/controllers/render-message-dispatcher.h>
45 #include <dali/internal/update/controllers/scene-controller-impl.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/render-task-processor.h>
48 #include <dali/internal/update/manager/sorted-layers.h>
49 #include <dali/internal/update/manager/update-algorithms.h>
50 #include <dali/internal/update/manager/update-manager-debug.h>
51 #include <dali/internal/update/manager/transform-manager.h>
52 #include <dali/internal/update/nodes/node.h>
53 #include <dali/internal/update/nodes/scene-graph-layer.h>
54 #include <dali/internal/update/queue/update-message-queue.h>
55 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
57 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
59 #include <dali/internal/render/common/render-instruction-container.h>
60 #include <dali/internal/render/common/render-manager.h>
61 #include <dali/internal/render/queue/render-queue.h>
62 #include <dali/internal/render/shaders/scene-graph-shader.h>
64 // Un-comment to enable node tree debug logging
65 //#define NODE_TREE_LOGGING 1
67 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
68 #define SNAPSHOT_NODE_LOGGING \
69 const int FRAME_COUNT_TRIGGER = 16;\
70 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
72 if ( NULL != mImpl->root )\
74 mImpl->frameCounter = 0;\
75 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
78 mImpl->frameCounter++;
80 #define SNAPSHOT_NODE_LOGGING
83 #if defined(DEBUG_ENABLED)
84 extern Debug::Filter* gRenderTaskLogFilter;
88 using namespace Dali::Integration;
89 using Dali::Internal::Update::MessageQueue;
103 * Helper to reset animate-able objects to base values
104 * @param container to iterate over
105 * @param updateBufferIndex to use
108 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
110 // Reset animatable properties to base values
111 // use reference to avoid extra copies of the iterator
112 for( auto&& iter : container )
114 iter->ResetToBaseValues( updateBufferIndex );
119 * Helper to Erase an object from OwnerContainer using discard queue
120 * @param container to remove from
121 * @param object to remove
122 * @param discardQueue to put the object to
123 * @param updateBufferIndex to use
126 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
128 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
130 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
131 for( auto&& iter : container )
133 if ( iter == object )
135 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
136 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
137 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
143 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
144 * @param[in] node The node whose hierarchy to descend
146 void SortSiblingNodesRecursively( Node& node )
148 NodeContainer& container = node.GetChildren();
149 std::sort( container.Begin(), container.End(),
150 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
152 // Descend tree and sort as well
153 for( auto&& iter : container )
155 SortSiblingNodesRecursively( *iter );
159 } // unnamed namespace
162 * Structure to contain UpdateManager internal data
164 struct UpdateManager::Impl
166 Impl( NotificationManager& notificationManager,
167 CompleteNotificationInterface& animationPlaylist,
168 PropertyNotifier& propertyNotifier,
169 DiscardQueue& discardQueue,
170 RenderController& renderController,
171 RenderManager& renderManager,
172 RenderQueue& renderQueue,
173 SceneGraphBuffers& sceneGraphBuffers,
174 RenderTaskProcessor& renderTaskProcessor )
175 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
176 notificationManager( notificationManager ),
178 animationPlaylist( animationPlaylist ),
179 propertyNotifier( propertyNotifier ),
181 discardQueue( discardQueue ),
182 renderController( renderController ),
183 sceneController( NULL ),
184 renderManager( renderManager ),
185 renderQueue( renderQueue ),
186 renderInstructions( renderManager.GetRenderInstructionContainer() ),
187 renderTaskProcessor( renderTaskProcessor ),
188 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
189 taskList( renderMessageDispatcher ),
190 systemLevelTaskList( renderMessageDispatcher ),
192 systemLevelRoot( NULL ),
196 panGestureProcessor( NULL ),
197 messageQueue( renderController, sceneGraphBuffers ),
198 keepRenderingSeconds( 0.0f ),
199 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
201 animationFinishedDuringUpdate( false ),
202 previousUpdateScene( false ),
203 renderTaskWaiting( false ),
204 renderersAdded( false ),
205 surfaceRectChanged( false )
207 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
209 // create first 'dummy' node
215 // Disconnect render tasks from nodes, before destroying the nodes
216 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
217 for ( auto&& iter : tasks )
219 iter->SetSourceNode( NULL );
221 // ..repeat for system level RenderTasks
222 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
223 for ( auto&& iter : systemLevelTasks )
225 iter->SetSourceNode( NULL );
228 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
229 // like custom properties, which get released here
230 Vector<Node*>::Iterator iter = nodes.Begin()+1;
231 Vector<Node*>::Iterator endIter = nodes.End();
232 for(;iter!=endIter;++iter)
234 (*iter)->OnDestroy();
238 // If there is root, reset it, otherwise do nothing as rendering was never started
243 Node::Delete( root );
247 if( systemLevelRoot )
249 systemLevelRoot->OnDestroy();
251 Node::Delete( systemLevelRoot );
252 systemLevelRoot = NULL;
255 delete sceneController;
258 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
259 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
260 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
261 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
262 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
263 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
264 ShaderSaver* shaderSaver; ///< Saves shader binaries.
265 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
266 RenderController& renderController; ///< render controller
267 SceneControllerImpl* sceneController; ///< scene controller
268 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
269 RenderQueue& renderQueue; ///< Used to queue messages for the next render
270 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
271 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
273 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
275 RenderTaskList taskList; ///< The list of scene graph render-tasks
276 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
278 Layer* root; ///< The root node (root is a layer)
279 Layer* systemLevelRoot; ///< A separate root-node for system-level content
281 Vector<Node*> nodes; ///< A container of all instantiated nodes
283 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
284 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
286 OwnerContainer< Camera* > cameras; ///< A container of cameras
287 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
289 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
290 AnimationContainer animations; ///< A container of owned animations
291 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
292 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
293 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
294 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
295 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
297 MessageQueue messageQueue; ///< The messages queued from the event-thread
298 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
299 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
300 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
302 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
303 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
304 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
306 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
307 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
308 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
309 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
310 bool surfaceRectChanged; ///< True if the default surface rect is changed
314 Impl( const Impl& ); ///< Undefined
315 Impl& operator=( const Impl& ); ///< Undefined
318 UpdateManager::UpdateManager( NotificationManager& notificationManager,
319 CompleteNotificationInterface& animationFinishedNotifier,
320 PropertyNotifier& propertyNotifier,
321 DiscardQueue& discardQueue,
322 RenderController& controller,
323 RenderManager& renderManager,
324 RenderQueue& renderQueue,
325 RenderTaskProcessor& renderTaskProcessor )
328 mImpl = new Impl( notificationManager,
329 animationFinishedNotifier,
336 renderTaskProcessor );
340 UpdateManager::~UpdateManager()
345 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
347 DALI_ASSERT_DEBUG( layer->IsLayer() );
348 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
352 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
353 mImpl->root = layer.Release();
354 mImpl->root->CreateTransform( &mImpl->transformManager );
355 mImpl->root->SetRoot(true);
359 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
360 mImpl->systemLevelRoot = layer.Release();
361 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
362 mImpl->systemLevelRoot->SetRoot(true);
367 void UpdateManager::AddNode( OwnerPointer<Node>& node )
369 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
371 // Nodes must be sorted by pointer
372 Node* rawNode = node.Release();
373 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
374 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
376 if( rawNode > (*iter) )
378 mImpl->nodes.Insert((iter+1), rawNode );
379 rawNode->CreateTransform( &mImpl->transformManager );
385 void UpdateManager::ConnectNode( Node* parent, Node* node )
387 DALI_ASSERT_ALWAYS( NULL != parent );
388 DALI_ASSERT_ALWAYS( NULL != node );
389 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
391 parent->ConnectChild( node );
394 void UpdateManager::DisconnectNode( Node* node )
396 Node* parent = node->GetParent();
397 DALI_ASSERT_ALWAYS( NULL != parent );
398 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
400 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
403 void UpdateManager::DestroyNode( Node* node )
405 DALI_ASSERT_ALWAYS( NULL != node );
406 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
408 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
409 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
410 for(;iter!=endIter;++iter)
414 mImpl->nodes.Erase(iter);
419 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
421 // Notify the Node about impending destruction
425 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
427 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
430 void UpdateManager::RemoveCamera( const Camera* camera )
432 // Find the camera and destroy it
433 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
436 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
438 mImpl->customObjects.PushBack( object.Release() );
441 void UpdateManager::RemoveObject( PropertyOwner* object )
443 mImpl->customObjects.EraseObject( object );
446 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
448 mImpl->animations.PushBack( animation.Release() );
451 void UpdateManager::StopAnimation( Animation* animation )
453 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
455 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
457 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
460 void UpdateManager::RemoveAnimation( Animation* animation )
462 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
464 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
466 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
469 bool UpdateManager::IsAnimationRunning() const
471 // Find any animation that isn't stopped or paused
472 for ( auto&& iter : mImpl->animations )
474 const Animation::State state = iter->GetState();
476 if (state != Animation::Stopped &&
477 state != Animation::Paused)
479 return true; // stop iteration as soon as first one is found
486 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
488 propertyResetter->Initialize();
489 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
492 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
494 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
497 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
499 mImpl->propertyNotifications.EraseObject( propertyNotification );
502 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
504 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
505 propertyNotification->SetNotifyMode( notifyMode );
508 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
510 mImpl->shaders.PushBack( shader.Release() );
513 void UpdateManager::RemoveShader( Shader* shader )
515 // Find the shader and destroy it
516 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
519 void UpdateManager::SetShaderProgram( Shader* shader,
520 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 // Reset all animating / constrained properties
618 std::vector<PropertyResetterBase*>toDelete;
619 for( auto&& element : mImpl->propertyResetters )
621 element->ResetToBaseValue( bufferIndex );
622 if( element->IsFinished() )
624 toDelete.push_back( element );
628 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
629 for( auto&& elementPtr : toDelete )
631 mImpl->propertyResetters.EraseObject( elementPtr );
634 // Clear node dirty flags
635 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
636 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
637 for( ;iter != endIter; ++iter )
639 (*iter)->ResetDirtyFlags( bufferIndex );
643 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
645 bool gestureUpdated( false );
647 if( mImpl->panGestureProcessor )
649 // gesture processor only supports default properties
650 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
651 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
654 return gestureUpdated;
657 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
659 AnimationContainer &animations = mImpl->animations;
660 AnimationIter iter = animations.Begin();
661 bool animationLooped = false;
663 while ( iter != animations.End() )
665 Animation* animation = *iter;
666 bool finished = false;
668 bool progressMarkerReached = false;
669 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
671 if ( progressMarkerReached )
673 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
676 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
677 animationLooped = animationLooped || looped;
679 // Remove animations that had been destroyed but were still waiting for an update
680 if (animation->GetState() == Animation::Destroyed)
682 iter = animations.Erase(iter);
690 // queue the notification on finished or looped (to update loop count)
691 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
693 // The application should be notified by NotificationManager, in another thread
694 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
698 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
700 //Constrain custom objects (in construction order)
701 for ( auto&& object : mImpl->customObjects )
703 ConstrainPropertyOwner( *object, bufferIndex );
707 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
709 // Constrain system-level render-tasks
710 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
711 for ( auto&& task : systemLevelTasks )
713 ConstrainPropertyOwner( *task, bufferIndex );
716 // Constrain render-tasks
717 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
718 for ( auto&& task : tasks )
720 ConstrainPropertyOwner( *task, bufferIndex );
724 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
726 // constrain shaders... (in construction order)
727 for ( auto&& shader : mImpl->shaders )
729 ConstrainPropertyOwner( *shader, bufferIndex );
733 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
735 for( auto&& notification : mImpl->propertyNotifications )
737 bool valid = notification->Check( bufferIndex );
740 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
745 void UpdateManager::ForwardCompiledShadersToEventThread()
747 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
748 if( mImpl->shaderSaver )
750 // lock and swap the queues
752 // render might be attempting to send us more binaries at the same time
753 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
754 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
757 if( mImpl->updateCompiledShaders.size() > 0 )
759 ShaderSaver& factory = *mImpl->shaderSaver;
760 for( auto&& shader : mImpl->updateCompiledShaders )
762 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
764 // we don't need them in update anymore
765 mImpl->updateCompiledShaders.clear();
770 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
772 const unsigned int rendererCount = mImpl->renderers.Count();
773 for( unsigned int i = 0; i < rendererCount; ++i )
776 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
778 mImpl->renderers[i]->PrepareRender( bufferIndex );
782 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
784 mImpl->nodeDirtyFlags = NothingFlag;
791 // Prepare resources, update shaders, for each node
792 // And add the renderers to the sorted layers. Start from root, which is also a layer
793 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
795 mImpl->renderQueue );
797 if ( mImpl->systemLevelRoot )
799 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
801 mImpl->renderQueue );
805 unsigned int UpdateManager::Update( float elapsedSeconds,
806 unsigned int lastVSyncTimeMilliseconds,
807 unsigned int nextVSyncTimeMilliseconds,
808 bool renderToFboEnabled,
809 bool isRenderingToFbo )
811 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
813 //Clear nodes/resources which were previously discarded
814 mImpl->discardQueue.Clear( bufferIndex );
816 //Process Touches & Gestures
817 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
819 bool updateScene = // The scene-graph requires an update if..
820 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
821 IsAnimationRunning() || // ..at least one animation is running OR
822 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
823 gestureUpdated; // ..a gesture property was updated
826 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
827 // values if the scene was updated in the previous frame.
828 if( updateScene || mImpl->previousUpdateScene )
830 //Reset properties from the previous update
831 ResetProperties( bufferIndex );
832 mImpl->transformManager.ResetToBaseValue();
835 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
836 // between calling IsSceneUpdateRequired() above and here, so updateScene should
838 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
840 //Forward compiled shader programs to event thread for saving
841 ForwardCompiledShadersToEventThread();
843 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
844 // renderer lists if the scene was updated in the previous frame.
845 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
846 if( updateScene || mImpl->previousUpdateScene )
849 Animate( bufferIndex, elapsedSeconds );
851 //Constraint custom objects
852 ConstrainCustomObjects( bufferIndex );
854 //Clear the lists of renderers from the previous update
855 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
857 mImpl->sortedLayers[i]->ClearRenderables();
860 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
862 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
865 //Update node hierarchy, apply constraints and perform sorting / culling.
866 //This will populate each Layer with a list of renderers which are ready.
867 UpdateNodes( bufferIndex );
869 //Apply constraints to RenderTasks, shaders
870 ConstrainRenderTasks( bufferIndex );
871 ConstrainShaders( bufferIndex );
873 //Update renderers and apply constraints
874 UpdateRenderers( bufferIndex );
876 //Update the transformations of all the nodes
877 mImpl->transformManager.Update();
879 //Process Property Notifications
880 ProcessPropertyNotifications( bufferIndex );
883 for( auto&& cameraIterator : mImpl->cameras )
885 cameraIterator->Update( bufferIndex );
888 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
889 //reset the update buffer index and make sure there is enough room in the instruction container
890 if( mImpl->renderersAdded )
892 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
893 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
895 if ( NULL != mImpl->root )
897 mImpl->renderTaskProcessor.Process( bufferIndex,
901 mImpl->renderInstructions,
905 // Process the system-level RenderTasks last
906 if ( NULL != mImpl->systemLevelRoot )
908 mImpl->renderTaskProcessor.Process( bufferIndex,
909 mImpl->systemLevelTaskList,
910 *mImpl->systemLevelRoot,
911 mImpl->systemLevelSortedLayers,
912 mImpl->renderInstructions,
920 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
921 bool doRenderOnceNotify = false;
922 mImpl->renderTaskWaiting = false;
923 for ( auto&& renderTask : mImpl->taskList.GetTasks() )
925 renderTask->UpdateState();
927 if( renderTask->IsWaitingToRender() &&
928 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
930 mImpl->renderTaskWaiting = true; // keep update/render threads alive
933 if( renderTask->HasRendered() )
935 doRenderOnceNotify = true;
939 if( doRenderOnceNotify )
941 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
942 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
945 // Macro is undefined in release build.
946 SNAPSHOT_NODE_LOGGING;
948 // A ResetProperties() may be required in the next frame
949 mImpl->previousUpdateScene = updateScene;
951 // Check whether further updates are required
952 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
954 // tell the update manager that we're done so the queue can be given to event thread
955 mImpl->notificationManager.UpdateCompleted();
957 // The update has finished; swap the double-buffering indices
958 mSceneGraphBuffers.Swap();
963 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
965 // Update the duration set via Stage::KeepRendering()
966 if ( mImpl->keepRenderingSeconds > 0.0f )
968 mImpl->keepRenderingSeconds -= elapsedSeconds;
971 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
973 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
974 // Keep updating until no messages are received and no animations are running.
975 // If an animation has just finished, update at least once more for Discard end-actions.
976 // No need to check for renderQueue as there is always a render after update and if that
977 // render needs another update it will tell the adaptor to call update again
979 if ( mImpl->keepRenderingSeconds > 0.0f )
981 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
984 if ( IsAnimationRunning() ||
985 mImpl->animationFinishedDuringUpdate )
987 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
990 if ( mImpl->renderTaskWaiting )
992 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
995 return keepUpdatingRequest;
998 void UpdateManager::SetBackgroundColor( const Vector4& color )
1000 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1002 // Reserve some memory inside the render queue
1003 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1005 // Construct message in the render queue memory; note that delete should not be called on the return value
1006 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1009 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1011 mImpl->surfaceRectChanged = true;
1013 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1015 // Reserve some memory inside the render queue
1016 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1018 // Construct message in the render queue memory; note that delete should not be called on the return value
1019 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1022 void UpdateManager::KeepRendering( float durationSeconds )
1024 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1027 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1031 // just copy the vector of pointers
1032 mImpl->sortedLayers = layers;
1036 mImpl->systemLevelSortedLayers = layers;
1040 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1042 // note,this vector is already in depth order. It could be used as-is to
1043 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1044 for( auto&& iter : nodeDepths->nodeDepths )
1046 iter.node->SetDepthIndex( iter.sortedDepth );
1049 // Go through node hierarchy and rearrange siblings according to depth-index
1050 SortSiblingNodesRecursively( *( mImpl->root ) );
1053 bool UpdateManager::IsDefaultSurfaceRectChanged()
1055 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1058 mImpl->surfaceRectChanged = false;
1060 return surfaceRectChanged;
1063 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1065 // Message has ownership of Sampler while in transit from update to render
1066 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1068 // Reserve some memory inside the render queue
1069 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1071 // Construct message in the render queue memory; note that delete should not be called on the return value
1072 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1075 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1077 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1079 // Reserve some memory inside the render queue
1080 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1082 // Construct message in the render queue memory; note that delete should not be called on the return value
1083 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1086 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1088 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1090 // Reserve some memory inside the render queue
1091 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1093 // Construct message in the render queue memory; note that delete should not be called on the return value
1094 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1097 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1099 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1101 // Reserve some memory inside the render queue
1102 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1104 // Construct message in the render queue memory; note that delete should not be called on the return value
1105 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1108 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1110 // Message has ownership of format while in transit from update -> render
1111 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1113 // Reserve some memory inside the render queue
1114 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1116 // Construct message in the render queue memory; note that delete should not be called on the return value
1117 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1120 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1122 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1124 // Reserve some memory inside the render queue
1125 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1127 // Construct message in the render queue memory; note that delete should not be called on the return value
1128 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1131 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1133 // Message has ownership of format while in transit from update -> render
1134 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1136 // Reserve some memory inside the render queue
1137 unsigned int* 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::SetPropertyBufferFormat, propertyBuffer, format );
1143 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
1145 // Message has ownership of format while in transit from update -> render
1146 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1148 // Reserve some memory inside the render queue
1149 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1151 // Construct message in the render queue memory; note that delete should not be called on the return value
1152 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1155 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1157 // Message has ownership of format while in transit from update -> render
1158 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1160 // Reserve some memory inside the render queue
1161 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1163 // Construct message in the render queue memory; note that delete should not be called on the return value
1164 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1167 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1169 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1171 // Reserve some memory inside the render queue
1172 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1174 // Construct message in the render queue memory; note that delete should not be called on the return value
1175 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1178 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1180 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1182 // Reserve some memory inside the render queue
1183 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1185 // Construct message in the render queue memory; note that delete should not be called on the return value
1186 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1189 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1191 typedef IndexBufferMessage< RenderManager > DerivedType;
1193 // Reserve some memory inside the render queue
1194 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1196 // Construct message in the render queue memory; note that delete should not be called on the return value
1197 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1200 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1202 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1204 // Reserve some memory inside the render queue
1205 unsigned int* 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::RemoveVertexBuffer, geometry, propertyBuffer );
1211 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1213 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1215 // Reserve some memory inside the render queue
1216 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1218 // Construct message in the render queue memory; note that delete should not be called on the return value
1219 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1222 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1224 // Message has ownership of Texture while in transit from update -> render
1225 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1227 // Reserve some memory inside the render queue
1228 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1230 // Construct message in the render queue memory; note that delete should not be called on the return value
1231 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1234 void UpdateManager::RemoveTexture( Render::Texture* texture)
1236 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1238 // Reserve some memory inside the render queue
1239 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1241 // Construct message in the render queue memory; note that delete should not be called on the return value
1242 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1245 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1247 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1249 // Reserve some memory inside the message queue
1250 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1252 // Construct message in the message queue memory; note that delete should not be called on the return value
1253 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1256 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1258 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1260 // Reserve some memory inside the render queue
1261 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1263 // Construct message in the render queue memory; note that delete should not be called on the return value
1264 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1267 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1269 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1271 // Reserve some memory inside the render queue
1272 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1274 // Construct message in the render queue memory; note that delete should not be called on the return value
1275 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1278 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1280 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1282 // Reserve some memory inside the render queue
1283 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1285 // Construct message in the render queue memory; note that delete should not be called on the return value
1286 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1289 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1291 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1293 // Reserve some memory inside the render queue
1294 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1296 // Construct message in the render queue memory; note that delete should not be called on the return value
1297 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1300 } // namespace SceneGraph
1302 } // namespace Internal