2 * Copyright (c) 2015 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/set-wrapper.h>
24 #include <dali/devel-api/common/owner-container.h>
25 #include <dali/devel-api/threading/mutex.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/integration-api/render-controller.h>
29 #include <dali/internal/common/shader-data.h>
30 #include <dali/integration-api/debug.h>
32 #include <dali/internal/common/core-impl.h>
33 #include <dali/internal/common/message.h>
35 #include <dali/internal/event/common/notification-manager.h>
36 #include <dali/internal/event/common/property-notification-impl.h>
37 #include <dali/internal/event/common/property-notifier.h>
38 #include <dali/internal/event/effects/shader-factory.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/object-owner-container.h>
48 #include <dali/internal/update/manager/process-render-tasks.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/manager/transform-manager.h>
53 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
54 #include <dali/internal/update/nodes/node.h>
55 #include <dali/internal/update/nodes/scene-graph-layer.h>
56 #include <dali/internal/update/queue/update-message-queue.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
58 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
59 #include <dali/internal/update/rendering/scene-graph-texture-set.h>
60 #include <dali/internal/update/resources/resource-manager.h>
61 #include <dali/internal/update/touch/touch-resampler.h>
63 #include <dali/internal/render/common/render-instruction-container.h>
64 #include <dali/internal/render/common/render-manager.h>
65 #include <dali/internal/render/queue/render-queue.h>
66 #include <dali/internal/render/gl-resources/texture-cache.h>
67 #include <dali/internal/render/shaders/scene-graph-shader.h>
68 #include <dali/internal/render/renderers/render-sampler.h>
70 // Un-comment to enable node tree debug logging
71 //#define NODE_TREE_LOGGING 1
73 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
74 #define SNAPSHOT_NODE_LOGGING \
75 const int FRAME_COUNT_TRIGGER = 16;\
76 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
78 if ( NULL != mImpl->root )\
80 mImpl->frameCounter = 0;\
81 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
84 mImpl->frameCounter++;
86 #define SNAPSHOT_NODE_LOGGING
89 #if defined(DEBUG_ENABLED)
90 extern Debug::Filter* gRenderTaskLogFilter;
94 using namespace Dali::Integration;
95 using Dali::Internal::Update::MessageQueue;
106 typedef OwnerContainer< Shader* > ShaderContainer;
107 typedef ShaderContainer::Iterator ShaderIter;
108 typedef ShaderContainer::ConstIterator ShaderConstIter;
110 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
112 typedef OwnerContainer<PanGesture*> GestureContainer;
113 typedef GestureContainer::Iterator GestureIter;
114 typedef GestureContainer::ConstIterator GestureConstIter;
116 typedef OwnerContainer< TextureSet* > TextureSetContainer;
117 typedef TextureSetContainer::Iterator TextureSetIter;
118 typedef TextureSetContainer::ConstIterator TextureSetConstIter;
121 * Structure to contain UpdateManager internal data
123 struct UpdateManager::Impl
125 Impl( NotificationManager& notificationManager,
126 CompleteNotificationInterface& animationFinishedNotifier,
127 PropertyNotifier& propertyNotifier,
128 ResourceManager& resourceManager,
129 DiscardQueue& discardQueue,
130 RenderController& renderController,
131 RenderManager& renderManager,
132 RenderQueue& renderQueue,
133 TextureCache& textureCache,
134 TouchResampler& touchResampler,
135 SceneGraphBuffers& sceneGraphBuffers )
136 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
137 notificationManager( notificationManager ),
139 animationFinishedNotifier( animationFinishedNotifier ),
140 propertyNotifier( propertyNotifier ),
142 resourceManager( resourceManager ),
143 discardQueue( discardQueue ),
144 renderController( renderController ),
145 sceneController( NULL ),
146 renderManager( renderManager ),
147 renderQueue( renderQueue ),
148 renderInstructions( renderManager.GetRenderInstructionContainer() ),
149 touchResampler( touchResampler ),
150 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
151 taskList( renderMessageDispatcher, resourceManager ),
152 systemLevelTaskList( renderMessageDispatcher, resourceManager ),
154 systemLevelRoot( NULL ),
155 renderers( sceneGraphBuffers, discardQueue ),
157 messageQueue( renderController, sceneGraphBuffers ),
158 keepRenderingSeconds( 0.0f ),
159 animationFinishedDuringUpdate( false ),
160 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
161 previousUpdateScene( false ),
163 renderSortingHelper(),
164 renderTaskWaiting( false )
166 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache );
168 renderers.SetSceneController( *sceneController );
170 // create first 'dummy' node
176 // Disconnect render tasks from nodes, before destroying the nodes
177 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
178 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
180 (*iter)->SetSourceNode( NULL );
182 // ..repeat for system level RenderTasks
183 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
184 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
186 (*iter)->SetSourceNode( NULL );
189 // UpdateManager owns the Nodes
190 Vector<Node*>::Iterator iter = nodes.Begin()+1;
191 Vector<Node*>::Iterator endIter = nodes.End();
192 for(;iter!=endIter;++iter)
194 (*iter)->OnDestroy();
198 // If there is root, reset it, otherwise do nothing as rendering was never started
207 if( systemLevelRoot )
209 systemLevelRoot->OnDestroy();
211 delete systemLevelRoot;
212 systemLevelRoot = NULL;
215 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
216 delete sceneController;
219 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
220 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
221 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
222 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
223 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
224 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
225 ShaderSaver* shaderSaver; ///< Saves shader binaries.
226 ResourceManager& resourceManager; ///< resource manager
227 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
228 RenderController& renderController; ///< render controller
229 SceneControllerImpl* sceneController; ///< scene controller
230 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
231 RenderQueue& renderQueue; ///< Used to queue messages for the next render
232 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
233 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
235 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
237 RenderTaskList taskList; ///< The list of scene graph render-tasks
238 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
240 Layer* root; ///< The root node (root is a layer)
241 Layer* systemLevelRoot; ///< A separate root-node for system-level content
243 Vector<Node*> nodes; ///< A container of all instantiated nodes
245 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
246 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
248 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
250 AnimationContainer animations; ///< A container of owned animations
251 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
253 ObjectOwnerContainer<Renderer> renderers;
254 TextureSetContainer textureSets; ///< A container of texture sets
256 ShaderContainer shaders; ///< A container of owned shaders
258 MessageQueue messageQueue; ///< The messages queued from the event-thread
259 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
260 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
261 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
263 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
264 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
266 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
267 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
269 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
270 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
272 GestureContainer gestures; ///< A container of owned gesture detectors
273 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
276 UpdateManager::UpdateManager( NotificationManager& notificationManager,
277 CompleteNotificationInterface& animationFinishedNotifier,
278 PropertyNotifier& propertyNotifier,
279 ResourceManager& resourceManager,
280 DiscardQueue& discardQueue,
281 RenderController& controller,
282 RenderManager& renderManager,
283 RenderQueue& renderQueue,
284 TextureCache& textureCache,
285 TouchResampler& touchResampler )
288 mImpl = new Impl( notificationManager,
289 animationFinishedNotifier,
298 mSceneGraphBuffers );
300 textureCache.SetBufferIndices( &mSceneGraphBuffers );
303 UpdateManager::~UpdateManager()
308 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
310 DALI_ASSERT_DEBUG( layer->IsLayer() );
311 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
315 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
317 mImpl->root->CreateTransform( &mImpl->transformManager);
321 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
322 mImpl->systemLevelRoot = layer;
323 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager);
326 layer->SetRoot(true);
329 void UpdateManager::AddNode( Node* node )
331 DALI_ASSERT_ALWAYS( NULL != node );
332 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
334 // Nodes must be sorted by pointer
335 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
336 for(Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter)
340 mImpl->nodes.Insert((iter+1), node);
341 node->CreateTransform( &mImpl->transformManager);
347 void UpdateManager::ConnectNode( Node* parent, Node* node )
349 DALI_ASSERT_ALWAYS( NULL != parent );
350 DALI_ASSERT_ALWAYS( NULL != node );
351 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
353 parent->ConnectChild( node );
356 void UpdateManager::DisconnectNode( Node* node )
358 Node* parent = node->GetParent();
359 DALI_ASSERT_ALWAYS( NULL != parent );
360 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
362 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
365 void UpdateManager::DestroyNode( Node* node )
367 DALI_ASSERT_ALWAYS( NULL != node );
368 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
370 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
371 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
372 for(;iter!=endIter;++iter)
376 mImpl->nodes.Erase(iter);
381 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
383 // Notify the Node about impending destruction
387 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
388 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
390 DALI_ASSERT_DEBUG( node != NULL );
391 DALI_ASSERT_DEBUG( attachment != NULL );
393 // attach node to attachment first so that parent is known by the time attachment is connected
394 node->Attach( *attachment ); // node takes ownership
397 void UpdateManager::AddObject( PropertyOwner* object )
399 DALI_ASSERT_DEBUG( NULL != object );
401 mImpl->customObjects.PushBack( object );
404 void UpdateManager::RemoveObject( PropertyOwner* object )
406 DALI_ASSERT_DEBUG( NULL != object );
408 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
410 // Find the object and destroy it
411 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
413 PropertyOwner* current = *iter;
414 if ( current == object )
416 customObjects.Erase( iter );
421 // Should not reach here
422 DALI_ASSERT_DEBUG(false);
425 void UpdateManager::AddAnimation( Animation* animation )
427 mImpl->animations.PushBack( animation );
430 void UpdateManager::StopAnimation( Animation* animation )
432 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
434 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
436 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
439 void UpdateManager::RemoveAnimation( Animation* animation )
441 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
443 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
445 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
448 bool UpdateManager::IsAnimationRunning() const
450 bool isRunning(false);
451 AnimationContainer& animations = mImpl->animations;
453 // Find any animation that isn't stopped or paused
455 const AnimationIter endIter = animations.End();
456 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
458 const Animation::State state = (*iter)->GetState();
460 if (state != Animation::Stopped &&
461 state != Animation::Paused)
470 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
472 mImpl->propertyNotifications.PushBack( propertyNotification );
475 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
477 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
478 PropertyNotificationIter iter = propertyNotifications.Begin();
480 while ( iter != propertyNotifications.End() )
482 if( *iter == propertyNotification )
484 propertyNotifications.Erase(iter);
491 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
493 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
494 propertyNotification->SetNotifyMode( notifyMode );
497 ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
499 return mImpl->renderers;
502 void UpdateManager::AddShader( Shader* shader )
504 DALI_ASSERT_DEBUG( NULL != shader );
506 if( mImpl->shaders.Count() == 0 )
508 // the first added shader becomes our default shader
509 // Construct message in the render queue memory; note that delete should not be called on the return value
510 typedef MessageValue1< RenderManager, Shader* > DerivedType;
512 // Reserve some memory inside the render queue
513 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
515 // Construct message in the render queue memory; note that delete should not be called on the return value
516 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
519 mImpl->shaders.PushBack( shader );
522 void UpdateManager::RemoveShader( Shader* shader )
524 DALI_ASSERT_DEBUG(shader != NULL);
526 ShaderContainer& shaders = mImpl->shaders;
528 // Find the shader and destroy it
529 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
531 Shader& current = **iter;
532 if ( ¤t == shader )
534 // Transfer ownership to the discard queue
535 // This keeps the shader alive, until the render-thread has finished with it
536 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
541 // Should not reach here
542 DALI_ASSERT_DEBUG(false);
545 void UpdateManager::SetShaderProgram( Shader* shader,
546 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
551 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
553 // Reserve some memory inside the render queue
554 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
556 // Construct message in the render queue memory; note that delete should not be called on the return value
557 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
561 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
563 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
564 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
566 // lock as update might be sending previously compiled shaders to event thread
567 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
568 mImpl->renderCompiledShaders.push_back( shaderData );
572 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
576 // copy the list, this is only likely to happen once in application life cycle
577 return &(mImpl->taskList);
581 // copy the list, this is only likely to happen once in application life cycle
582 return &(mImpl->systemLevelTaskList);
586 void UpdateManager::AddGesture( PanGesture* gesture )
588 DALI_ASSERT_DEBUG( NULL != gesture );
590 mImpl->gestures.PushBack( gesture );
593 void UpdateManager::RemoveGesture( PanGesture* gesture )
595 DALI_ASSERT_DEBUG( gesture != NULL );
597 GestureContainer& gestures = mImpl->gestures;
599 // Find the gesture and destroy it
600 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
602 PanGesture& current = **iter;
603 if ( ¤t == gesture )
605 mImpl->gestures.Erase( iter );
609 // Should not reach here
610 DALI_ASSERT_DEBUG(false);
613 void UpdateManager::AddTextureSet( TextureSet* textureSet )
615 DALI_ASSERT_DEBUG( NULL != textureSet );
616 mImpl->textureSets.PushBack( textureSet );
619 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
621 DALI_ASSERT_DEBUG(textureSet != NULL);
622 size_t textureSetCount( mImpl->textureSets.Size() );
623 for( size_t i(0); i<textureSetCount; ++i )
625 if( textureSet == mImpl->textureSets[i] )
627 mImpl->textureSets.Remove( mImpl->textureSets.Begin() + i );
633 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
635 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
638 void UpdateManager::EventProcessingStarted()
640 mImpl->messageQueue.EventProcessingStarted();
643 bool UpdateManager::FlushQueue()
645 return mImpl->messageQueue.FlushQueue();
648 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
650 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
651 mImpl->animationFinishedDuringUpdate = false;
653 // Animated properties have to be reset to their original value each frame
655 // Reset root properties
658 mImpl->root->ResetToBaseValues( bufferIndex );
660 if ( mImpl->systemLevelRoot )
662 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
665 // Reset all the nodes
666 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
667 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
668 for(;iter != endIter; ++iter)
670 (*iter)->ResetToBaseValues( bufferIndex );
673 // Reset system-level render-task list properties to base values
674 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
676 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
678 (*iter)->ResetToBaseValues( bufferIndex );
681 // Reset render-task list properties to base values.
682 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
684 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
686 (*iter)->ResetToBaseValues( bufferIndex );
689 // Reset custom object properties to base values
690 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
692 (*iter)->ResetToBaseValues( bufferIndex );
695 mImpl->renderers.ResetToBaseValues( bufferIndex );
697 // Reset animatable shader properties to base values
698 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
700 (*iter)->ResetToBaseValues( bufferIndex );
704 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
706 bool gestureUpdated( false );
708 // constrain gestures... (in construction order)
709 GestureContainer& gestures = mImpl->gestures;
711 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
713 PanGesture& gesture = **iter;
714 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
715 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
718 return gestureUpdated;
721 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
723 AnimationContainer &animations = mImpl->animations;
724 AnimationIter iter = animations.Begin();
725 bool animationLooped = false;
726 while ( iter != animations.End() )
728 Animation* animation = *iter;
729 bool finished = false;
731 animation->Update( bufferIndex, elapsedSeconds, looped, finished );
733 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
734 animationLooped = animationLooped || looped;
736 // Remove animations that had been destroyed but were still waiting for an update
737 if (animation->GetState() == Animation::Destroyed)
739 iter = animations.Erase(iter);
747 // queue the notification on finished or looped (to update loop count)
748 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
750 // The application should be notified by NotificationManager, in another thread
751 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
755 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
757 //Constrain custom objects (in construction order)
758 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
759 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
760 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
762 PropertyOwner& object = **iter;
763 ConstrainPropertyOwner( object, bufferIndex );
767 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
769 // Constrain system-level render-tasks
770 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
771 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
773 RenderTask& task = **iter;
774 ConstrainPropertyOwner( task, bufferIndex );
777 // Constrain render-tasks
778 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
779 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
781 RenderTask& task = **iter;
782 ConstrainPropertyOwner( task, bufferIndex );
786 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
788 // constrain shaders... (in construction order)
789 ShaderContainer& shaders = mImpl->shaders;
790 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
792 Shader& shader = **iter;
793 ConstrainPropertyOwner( shader, bufferIndex );
797 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
799 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
800 PropertyNotificationIter iter = notifications.Begin();
802 while ( iter != notifications.End() )
804 PropertyNotification* notification = *iter;
805 bool valid = notification->Check( bufferIndex );
808 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
814 void UpdateManager::PrepareTextureSets( BufferIndex bufferIndex )
816 size_t textureSetCount( mImpl->textureSets.Size() );
817 for( size_t i(0); i<textureSetCount; ++i )
819 //Prepare texture set
820 mImpl->textureSets[i]->Prepare( mImpl->resourceManager );
824 void UpdateManager::ForwardCompiledShadersToEventThread()
826 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
827 if( mImpl->shaderSaver )
829 // lock and swap the queues
831 // render might be attempting to send us more binaries at the same time
832 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
833 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
836 if( mImpl->updateCompiledShaders.size() > 0 )
838 ShaderSaver& factory = *mImpl->shaderSaver;
839 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
840 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
841 for( ; i != end; ++i )
843 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
845 // we don't need them in update anymore
846 mImpl->updateCompiledShaders.clear();
851 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
853 const OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
854 unsigned int rendererCount( rendererContainer.Size() );
855 for( unsigned int i(0); i<rendererCount; ++i )
858 ConstrainPropertyOwner( *rendererContainer[i], bufferIndex );
860 if( rendererContainer[i]->IsReferenced() )
862 rendererContainer[i]->PrepareRender( bufferIndex );
867 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
869 mImpl->nodeDirtyFlags = NothingFlag;
876 // Prepare resources, update shaders, update attachments, for each node
877 // And add the renderers to the sorted layers. Start from root, which is also a layer
878 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
880 mImpl->resourceManager,
881 mImpl->renderQueue );
883 if ( mImpl->systemLevelRoot )
885 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
887 mImpl->resourceManager,
888 mImpl->renderQueue );
892 unsigned int UpdateManager::Update( float elapsedSeconds,
893 unsigned int lastVSyncTimeMilliseconds,
894 unsigned int nextVSyncTimeMilliseconds )
896 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
898 //Clear nodes/resources which were previously discarded
899 mImpl->discardQueue.Clear( bufferIndex );
901 //Grab any loaded resources
902 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
904 //Process Touches & Gestures
905 mImpl->touchResampler.Update();
906 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
908 const bool updateScene = // The scene-graph requires an update if..
909 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
910 IsAnimationRunning() || // ..at least one animation is running OR
911 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
912 resourceChanged || // ..one or more resources were updated/changed OR
913 gestureUpdated; // ..a gesture property was updated
916 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
917 // values if the scene was updated in the previous frame.
918 if( updateScene || mImpl->previousUpdateScene )
920 //Reset properties from the previous update
921 ResetProperties( bufferIndex );
922 mImpl->transformManager.ResetToBaseValue();
925 //Process the queued scene messages
926 mImpl->messageQueue.ProcessMessages( bufferIndex );
928 //Post Process Ids of resources updated by renderer
929 mImpl->resourceManager.PostProcessResources( bufferIndex );
931 //Forward compiled shader programs to event thread for saving
932 ForwardCompiledShadersToEventThread();
934 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
935 // renderer lists if the scene was updated in the previous frame.
936 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
937 if( updateScene || mImpl->previousUpdateScene )
940 Animate( bufferIndex, elapsedSeconds );
942 //Constraint custom objects
943 ConstrainCustomObjects( bufferIndex );
945 //Prepare texture sets and apply constraints to them
946 PrepareTextureSets( bufferIndex );
948 //Clear the lists of renderable-attachments from the previous update
949 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
951 mImpl->sortedLayers[i]->ClearRenderables();
954 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
956 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
959 //Update node hierarchy, apply constraints and perform sorting / culling.
960 //This will populate each Layer with a list of renderers which are ready.
961 UpdateNodes( bufferIndex );
963 //Apply constraints to RenderTasks, shaders
964 ConstrainRenderTasks( bufferIndex );
965 ConstrainShaders( bufferIndex );
967 //Update renderers and apply constraints
968 UpdateRenderers( bufferIndex );
970 //Update the trnasformations of all the nodes
971 mImpl->transformManager.Update();
973 //Process Property Notifications
974 ProcessPropertyNotifications( bufferIndex );
976 //Process the RenderTasks; this creates the instructions for rendering the next frame.
977 //reset the update buffer index and make sure there is enough room in the instruction container
978 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
979 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
981 if ( NULL != mImpl->root )
983 ProcessRenderTasks( bufferIndex,
987 mImpl->renderSortingHelper,
988 mImpl->renderInstructions );
990 // Process the system-level RenderTasks last
991 if ( NULL != mImpl->systemLevelRoot )
993 ProcessRenderTasks( bufferIndex,
994 mImpl->systemLevelTaskList,
995 *mImpl->systemLevelRoot,
996 mImpl->systemLevelSortedLayers,
997 mImpl->renderSortingHelper,
998 mImpl->renderInstructions );
1003 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1004 bool doRenderOnceNotify = false;
1005 mImpl->renderTaskWaiting = false;
1006 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1007 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1008 endIter != iter; ++iter )
1010 RenderTask& renderTask(*(*iter));
1012 renderTask.UpdateState();
1014 if( renderTask.IsWaitingToRender() &&
1015 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1017 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1020 if( renderTask.HasRendered() )
1022 doRenderOnceNotify = true;
1026 if( doRenderOnceNotify )
1028 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1029 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1032 // Macro is undefined in release build.
1033 SNAPSHOT_NODE_LOGGING;
1035 // A ResetProperties() may be required in the next frame
1036 mImpl->previousUpdateScene = updateScene;
1038 // Check whether further updates are required
1039 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1041 // tell the update manager that we're done so the queue can be given to event thread
1042 mImpl->notificationManager.UpdateCompleted();
1044 // The update has finished; swap the double-buffering indices
1045 mSceneGraphBuffers.Swap();
1047 return keepUpdating;
1050 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1052 // Update the duration set via Stage::KeepRendering()
1053 if ( mImpl->keepRenderingSeconds > 0.0f )
1055 mImpl->keepRenderingSeconds -= elapsedSeconds;
1058 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1060 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1061 // Keep updating until no messages are received and no animations are running.
1062 // If an animation has just finished, update at least once more for Discard end-actions.
1063 // No need to check for renderQueue as there is always a render after update and if that
1064 // render needs another update it will tell the adaptor to call update again
1066 if ( mImpl->keepRenderingSeconds > 0.0f )
1068 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1071 if ( IsAnimationRunning() ||
1072 mImpl->animationFinishedDuringUpdate )
1074 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1077 if ( mImpl->renderTaskWaiting )
1079 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1082 return keepUpdatingRequest;
1085 void UpdateManager::SetBackgroundColor( const Vector4& color )
1087 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1089 // Reserve some memory inside the render queue
1090 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1092 // Construct message in the render queue memory; note that delete should not be called on the return value
1093 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1096 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1098 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1100 // Reserve some memory inside the render queue
1101 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1103 // Construct message in the render queue memory; note that delete should not be called on the return value
1104 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1107 void UpdateManager::KeepRendering( float durationSeconds )
1109 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1112 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1116 // just copy the vector of pointers
1117 mImpl->sortedLayers = layers;
1121 mImpl->systemLevelSortedLayers = layers;
1125 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1127 mImpl->shaderSaver = &upstream;
1130 void UpdateManager::AddSampler( Render::Sampler* sampler )
1132 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1134 // Reserve some memory inside the render queue
1135 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1137 // Construct message in the render queue memory; note that delete should not be called on the return value
1138 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1141 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1143 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1145 // Reserve some memory inside the render queue
1146 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1148 // Construct message in the render queue memory; note that delete should not be called on the return value
1149 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1152 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1154 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1156 // Reserve some memory inside the render queue
1157 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1159 // Construct message in the render queue memory; note that delete should not be called on the return value
1160 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1163 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int uWrapMode, unsigned int vWrapMode )
1165 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1167 // Reserve some memory inside the render queue
1168 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1170 // Construct message in the render queue memory; note that delete should not be called on the return value
1171 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, uWrapMode, vWrapMode );
1174 void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1176 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1178 // Reserve some memory inside the render queue
1179 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1181 // Construct message in the render queue memory; note that delete should not be called on the return value
1182 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1185 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1187 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1189 // Reserve some memory inside the render queue
1190 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1192 // Construct message in the render queue memory; note that delete should not be called on the return value
1193 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1196 void UpdateManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
1198 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, Render::PropertyBuffer::Format* > DerivedType;
1200 // Reserve some memory inside the render queue
1201 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1203 // Construct message in the render queue memory; note that delete should not be called on the return value
1204 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1207 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data, size_t size )
1209 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, Dali::Vector<char>*, size_t > DerivedType;
1211 // Reserve some memory inside the render queue
1212 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1214 // Construct message in the render queue memory; note that delete should not be called on the return value
1215 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1218 void UpdateManager::AddGeometry( Render::Geometry* geometry )
1220 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1222 // Reserve some memory inside the render queue
1223 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1225 // Construct message in the render queue memory; note that delete should not be called on the return value
1226 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1229 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1231 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1233 // Reserve some memory inside the render queue
1234 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1236 // Construct message in the render queue memory; note that delete should not be called on the return value
1237 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1240 void UpdateManager::SetGeometryRequiresDepthTest( Render::Geometry* geometry, bool requiresDepthTest )
1242 typedef MessageValue2< RenderManager, Render::Geometry*, bool > DerivedType;
1244 // Reserve some memory inside the render queue
1245 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1247 // Construct message in the render queue memory; note that delete should not be called on the return value
1248 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryRequiresDepthTest, geometry, requiresDepthTest );
1251 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1253 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1255 // Reserve some memory inside the render queue
1256 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1258 // Construct message in the render queue memory; note that delete should not be called on the return value
1259 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1262 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1264 typedef IndexBufferMessage< RenderManager > DerivedType;
1266 // Reserve some memory inside the render queue
1267 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1269 // Construct message in the render queue memory; note that delete should not be called on the return value
1270 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1273 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1275 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1277 // Reserve some memory inside the render queue
1278 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1280 // Construct message in the render queue memory; note that delete should not be called on the return value
1281 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1284 void UpdateManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1286 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1288 // Reserve some memory inside the render queue
1289 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1291 // Construct message in the render queue memory; note that delete should not be called on the return value
1292 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddVertexBuffer, geometry, propertyBuffer );
1296 } // namespace SceneGraph
1298 } // namespace Internal