Dali 3D User Interface Engine
update-manager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 
18 // CLASS HEADER
20 
21 // INTERNAL INCLUDES
26 
31 
34 
39 
62 
69 
70 // Un-comment to enable node tree debug logging
71 //#define NODE_TREE_LOGGING 1
72 
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 )\
77  {\
78  if ( NULL != mImpl->root )\
79  {\
80  mImpl->frameCounter = 0;\
81  PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
82  }\
83  }\
84 mImpl->frameCounter++;
85 #else
86 #define SNAPSHOT_NODE_LOGGING
87 #endif
88 
89 #if defined(DEBUG_ENABLED)
90 extern Debug::Filter* gRenderTaskLogFilter;
91 #endif
92 
93 
94 using namespace Dali::Integration;
96 
97 namespace Dali
98 {
99 
100 namespace Internal
101 {
102 
103 namespace SceneGraph
104 {
105 
109 
110 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
111 
115 
116 
121 {
122  Impl( NotificationManager& notificationManager,
123  CompleteNotificationInterface& animationFinishedNotifier,
124  PropertyNotifier& propertyNotifier,
125  ResourceManager& resourceManager,
126  DiscardQueue& discardQueue,
127  RenderController& renderController,
128  RenderManager& renderManager,
129  RenderQueue& renderQueue,
130  TextureCache& textureCache,
131  TouchResampler& touchResampler,
132  SceneGraphBuffers& sceneGraphBuffers )
133  :
134  renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
135  notificationManager( notificationManager ),
136  animationFinishedNotifier( animationFinishedNotifier ),
137  propertyNotifier( propertyNotifier ),
138  shaderSaver( NULL ),
139  resourceManager( resourceManager ),
140  discardQueue( discardQueue ),
141  renderController( renderController ),
142  sceneController( NULL ),
143  renderManager( renderManager ),
144  renderQueue( renderQueue ),
145  renderInstructions( renderManager.GetRenderInstructionContainer() ),
146  touchResampler( touchResampler ),
147  backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
148  taskList( renderMessageDispatcher, resourceManager ),
149  systemLevelTaskList( renderMessageDispatcher, resourceManager ),
150  root( NULL ),
151  systemLevelRoot( NULL ),
152  renderers( sceneGraphBuffers, discardQueue ),
153  geometries( sceneGraphBuffers, discardQueue ),
154  materials( sceneGraphBuffers, discardQueue ),
155  messageQueue( renderController, sceneGraphBuffers ),
156  keepRenderingSeconds( 0.0f ),
157  animationFinishedDuringUpdate( false ),
158  nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
159  previousUpdateScene( false ),
160  frameCounter( 0 ),
161  renderSortingHelper(),
162  renderTaskWaiting( false )
163  {
164  sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache );
165 
166  renderers.SetSceneController( *sceneController );
167  geometries.SetSceneController( *sceneController );
168  materials.SetSceneController( *sceneController );
169 
170  // create first 'dummy' node
171  nodes.PushBack(0u);
172  }
173 
174  ~Impl()
175  {
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)
179  {
180  (*iter)->SetSourceNode( NULL );
181  }
182  // ..repeat for system level RenderTasks
183  RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
184  for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
185  {
186  (*iter)->SetSourceNode( NULL );
187  }
188 
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)
193  {
194  (*iter)->OnDestroy();
195  delete(*iter);
196  }
197 
198  // If there is root, reset it, otherwise do nothing as rendering was never started
199  if( root )
200  {
201  root->OnDestroy();
202 
203  delete root;
204  root = NULL;
205  }
206 
207  if( systemLevelRoot )
208  {
209  systemLevelRoot->OnDestroy();
210 
211  delete systemLevelRoot;
212  systemLevelRoot = NULL;
213  }
214 
215  sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
216  delete sceneController;
217  }
218 
233 
235 
238 
241 
243 
246 
248 
251 
255 
257 
262 
265 
268 
271 
274 };
275 
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 )
286  : mImpl(NULL)
287 {
288  mImpl = new Impl( notificationManager,
289  animationFinishedNotifier,
290  propertyNotifier,
291  resourceManager,
292  discardQueue,
293  controller,
294  renderManager,
295  renderQueue,
296  textureCache,
297  touchResampler,
299 
300  textureCache.SetBufferIndices( &mSceneGraphBuffers );
301 }
302 
304 {
305  delete mImpl;
306 }
307 
308 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
309 {
310  DALI_ASSERT_DEBUG( layer->IsLayer() );
311  DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
312 
313  if ( !systemLevel )
314  {
315  DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
316  mImpl->root = layer;
317  }
318  else
319  {
320  DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
321  mImpl->systemLevelRoot = layer;
322  }
323 
324  layer->SetRoot(true);
325 }
326 
328 {
329  DALI_ASSERT_ALWAYS( NULL != node );
330  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
331 
332  // Nodes must be sorted by pointer
334  for(Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter)
335  {
336  if(node > (*iter))
337  {
338  mImpl->nodes.Insert((iter+1), node);
339  break;
340  }
341  }
342 }
343 
344 void UpdateManager::ConnectNode( Node* parent, Node* node )
345 {
346  DALI_ASSERT_ALWAYS( NULL != parent );
347  DALI_ASSERT_ALWAYS( NULL != node );
348  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
349 
350  parent->ConnectChild( node );
351 }
352 
354 {
355  Node* parent = node->GetParent();
356  DALI_ASSERT_ALWAYS( NULL != parent );
357  parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
358 
360 }
361 
363 {
364  DALI_ASSERT_ALWAYS( NULL != node );
365  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
366 
368  Vector<Node*>::Iterator endIter = mImpl->nodes.End();
369  for(;iter!=endIter;++iter)
370  {
371  if((*iter) == node)
372  {
373  mImpl->nodes.Erase(iter);
374  break;
375  }
376  }
377 
379 
380  // Notify the Node about impending destruction
381  node->OnDestroy();
382 }
383 
384 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
386 {
387  DALI_ASSERT_DEBUG( node != NULL );
388  DALI_ASSERT_DEBUG( attachment != NULL );
389 
390  // attach node to attachment first so that parent is known by the time attachment is connected
391  node->Attach( *attachment ); // node takes ownership
392 }
393 
395 {
396  DALI_ASSERT_DEBUG( NULL != object );
397 
398  mImpl->customObjects.PushBack( object );
399 }
400 
402 {
403  DALI_ASSERT_DEBUG( NULL != object );
404 
406 
407  // Find the object and destroy it
408  for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
409  {
410  PropertyOwner* current = *iter;
411  if ( current == object )
412  {
413  customObjects.Erase( iter );
414  return;
415  }
416  }
417 
418  // Should not reach here
419  DALI_ASSERT_DEBUG(false);
420 }
421 
423 {
424  mImpl->animations.PushBack( animation );
425 }
426 
428 {
429  DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
430 
431  bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
432 
434 }
435 
437 {
438  DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
439 
441 
443 }
444 
446 {
447  bool isRunning(false);
448  AnimationContainer& animations = mImpl->animations;
449 
450  // Find any animation that isn't stopped or paused
451 
452  const AnimationIter endIter = animations.End();
453  for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
454  {
455  const Animation::State state = (*iter)->GetState();
456 
457  if (state != Animation::Stopped &&
458  state != Animation::Paused)
459  {
460  isRunning = true;
461  }
462  }
463 
464  return isRunning;
465 }
466 
468 {
469  mImpl->propertyNotifications.PushBack( propertyNotification );
470 }
471 
473 {
475  PropertyNotificationIter iter = propertyNotifications.Begin();
476 
477  while ( iter != propertyNotifications.End() )
478  {
479  if( *iter == propertyNotification )
480  {
481  propertyNotifications.Erase(iter);
482  break;
483  }
484  ++iter;
485  }
486 }
487 
489 {
490  DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
491  propertyNotification->SetNotifyMode( notifyMode );
492 }
493 
495 {
496  return mImpl->geometries;
497 }
498 
500 {
501  return mImpl->renderers;
502 }
503 
504 
506 {
507  return mImpl->materials;
508 }
509 
511 {
512  DALI_ASSERT_DEBUG( NULL != shader );
513 
514  if( mImpl->shaders.Count() == 0 )
515  {
516  // the first added shader becomes our default shader
517  // Construct message in the render queue memory; note that delete should not be called on the return value
518  typedef MessageValue1< RenderManager, Shader* > DerivedType;
519 
520  // Reserve some memory inside the render queue
521  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
522 
523  // Construct message in the render queue memory; note that delete should not be called on the return value
524  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
525  }
526 
527  mImpl->shaders.PushBack( shader );
528 
529  // Allows the shader to dispatch texture requests to the cache
531 }
532 
534 {
535  DALI_ASSERT_DEBUG(shader != NULL);
536 
537  ShaderContainer& shaders = mImpl->shaders;
538 
539  // Find the shader and destroy it
540  for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
541  {
542  Shader& current = **iter;
543  if ( &current == shader )
544  {
545  // Transfer ownership to the discard queue
546  // This keeps the shader alive, until the render-thread has finished with it
548 
549  return;
550  }
551  }
552  // Should not reach here
553  DALI_ASSERT_DEBUG(false);
554 }
555 
557  Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
558 {
559  if( shaderData )
560  {
561 
563 
564  // Reserve some memory inside the render queue
565  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
566 
567  // Construct message in the render queue memory; note that delete should not be called on the return value
568  new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
569  }
570 }
571 
573 {
574  DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
575  DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
576  {
577  // lock as update might be sending previously compiled shaders to event thread
579  mImpl->renderCompiledShaders.push_back( shaderData );
580  }
581 }
582 
584 {
585  if ( !systemLevel )
586  {
587  // copy the list, this is only likely to happen once in application life cycle
588  return &(mImpl->taskList);
589  }
590  else
591  {
592  // copy the list, this is only likely to happen once in application life cycle
593  return &(mImpl->systemLevelTaskList);
594  }
595 }
596 
598 {
599  DALI_ASSERT_DEBUG( NULL != gesture );
600 
601  mImpl->gestures.PushBack( gesture );
602 }
603 
605 {
606  DALI_ASSERT_DEBUG( gesture != NULL );
607 
608  GestureContainer& gestures = mImpl->gestures;
609 
610  // Find the gesture and destroy it
611  for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
612  {
613  PanGesture& current = **iter;
614  if ( &current == gesture )
615  {
616  mImpl->gestures.Erase( iter );
617  return;
618  }
619  }
620  // Should not reach here
621  DALI_ASSERT_DEBUG(false);
622 }
623 
624 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
625 {
626  return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
627 }
628 
630 {
632 }
633 
635 {
636  return mImpl->messageQueue.FlushQueue();
637 }
638 
640 {
641  // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
643 
644  // Animated properties have to be reset to their original value each frame
645 
646  // Reset root properties
647  if ( mImpl->root )
648  {
649  mImpl->root->ResetToBaseValues( bufferIndex );
650  }
651  if ( mImpl->systemLevelRoot )
652  {
653  mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
654  }
655 
656  // Reset all the nodes
658  Vector<Node*>::Iterator endIter = mImpl->nodes.End();
659  for(;iter != endIter; ++iter)
660  {
661  (*iter)->ResetToBaseValues( bufferIndex );
662  }
663 
664  // Reset system-level render-task list properties to base values
666 
667  for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
668  {
669  (*iter)->ResetToBaseValues( bufferIndex );
670  }
671 
672  // Reset render-task list properties to base values.
674 
675  for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
676  {
677  (*iter)->ResetToBaseValues( bufferIndex );
678  }
679 
680  // Reset custom object properties to base values
681  for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
682  {
683  (*iter)->ResetToBaseValues( bufferIndex );
684  }
685 
686  mImpl->materials.ResetToBaseValues( bufferIndex );
687  mImpl->geometries.ResetToBaseValues( bufferIndex );
688  mImpl->renderers.ResetToBaseValues( bufferIndex );
689 
690  // Reset animatable shader properties to base values
691  for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
692  {
693  (*iter)->ResetToBaseValues( bufferIndex );
694  }
695 }
696 
697 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
698 {
699  bool gestureUpdated( false );
700 
701  // constrain gestures... (in construction order)
702  GestureContainer& gestures = mImpl->gestures;
703 
704  for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
705  {
706  PanGesture& gesture = **iter;
707  gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
708  gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
709  }
710 
711  return gestureUpdated;
712 }
713 
714 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
715 {
716  AnimationContainer &animations = mImpl->animations;
717  AnimationIter iter = animations.Begin();
718  bool animationLooped = false;
719  while ( iter != animations.End() )
720  {
721  Animation* animation = *iter;
722  bool finished = false;
723  bool looped = false;
724  animation->Update( bufferIndex, elapsedSeconds, looped, finished );
725 
727  animationLooped = animationLooped || looped;
728 
729  // Remove animations that had been destroyed but were still waiting for an update
730  if (animation->GetState() == Animation::Destroyed)
731  {
732  iter = animations.Erase(iter);
733  }
734  else
735  {
736  ++iter;
737  }
738  }
739 
740  // queue the notification on finished or looped (to update loop count)
741  if ( mImpl->animationFinishedDuringUpdate || animationLooped )
742  {
743  // The application should be notified by NotificationManager, in another thread
745  }
746 }
747 
749 {
750  //Constrain custom objects (in construction order)
752  const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
753  for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
754  {
755  PropertyOwner& object = **iter;
756  ConstrainPropertyOwner( object, bufferIndex );
757  }
758 }
759 
761 {
762  // Constrain system-level render-tasks
764  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
765  {
766  RenderTask& task = **iter;
767  ConstrainPropertyOwner( task, bufferIndex );
768  }
769 
770  // Constrain render-tasks
772  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
773  {
774  RenderTask& task = **iter;
775  ConstrainPropertyOwner( task, bufferIndex );
776  }
777 }
778 
780 {
781  // constrain shaders... (in construction order)
782  ShaderContainer& shaders = mImpl->shaders;
783  for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
784  {
785  Shader& shader = **iter;
786  ConstrainPropertyOwner( shader, bufferIndex );
787  }
788 }
789 
791 {
793  PropertyNotificationIter iter = notifications.Begin();
794 
795  while ( iter != notifications.End() )
796  {
797  PropertyNotification* notification = *iter;
798  bool valid = notification->Check( bufferIndex );
799  if(valid)
800  {
802  }
803  ++iter;
804  }
805 }
806 
808 {
809  ObjectOwnerContainer<Material>::Iterator iter = mImpl->materials.GetObjectContainer().Begin();
810  const ObjectOwnerContainer<Material>::Iterator end = mImpl->materials.GetObjectContainer().End();
811  for( ; iter != end; ++iter )
812  {
813  //Apply constraints
814  ConstrainPropertyOwner( *(*iter), bufferIndex );
815 
816  //Prepare material
817  (*iter)->Prepare( mImpl->resourceManager );
818  }
819 }
820 
822 {
823  DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
824  if( mImpl->shaderSaver )
825  {
826  // lock and swap the queues
827  {
828  // render might be attempting to send us more binaries at the same time
831  }
832 
833  if( mImpl->updateCompiledShaders.size() > 0 )
834  {
835  ShaderSaver& factory = *mImpl->shaderSaver;
836  ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
837  ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
838  for( ; i != end; ++i )
839  {
841  }
842  // we don't need them in update anymore
843  mImpl->updateCompiledShaders.clear();
844  }
845  }
846 }
847 
849 {
850  const OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
851  unsigned int rendererCount( rendererContainer.Size() );
852  for( unsigned int i(0); i<rendererCount; ++i )
853  {
854  //Apply constraints
855  ConstrainPropertyOwner( *rendererContainer[i], bufferIndex );
856 
857  if( rendererContainer[i]->IsReferenced() )
858  {
859  rendererContainer[i]->PrepareRender( bufferIndex );
860  }
861  }
862 }
863 
865 {
867 
868  if ( !mImpl->root )
869  {
870  return;
871  }
872 
873  // Prepare resources, update shaders, update attachments, for each node
874  // And add the renderers to the sorted layers. Start from root, which is also a layer
876  bufferIndex,
878  mImpl->renderQueue );
879 
880  if ( mImpl->systemLevelRoot )
881  {
883  bufferIndex,
885  mImpl->renderQueue );
886  }
887 }
888 
889 unsigned int UpdateManager::Update( float elapsedSeconds,
890  unsigned int lastVSyncTimeMilliseconds,
891  unsigned int nextVSyncTimeMilliseconds )
892 {
894 
895  //Clear nodes/resources which were previously discarded
896  mImpl->discardQueue.Clear( bufferIndex );
897 
898  //Grab any loaded resources
899  bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
900 
901  //Process Touches & Gestures
903  const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
904 
905  const bool updateScene = // The scene-graph requires an update if..
906  (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
907  IsAnimationRunning() || // ..at least one animation is running OR
908  mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
909  resourceChanged || // ..one or more resources were updated/changed OR
910  gestureUpdated; // ..a gesture property was updated
911 
912 
913  // Although the scene-graph may not require an update, we still need to synchronize double-buffered
914  // values if the scene was updated in the previous frame.
915  if( updateScene || mImpl->previousUpdateScene )
916  {
917  //Reset properties from the previous update
918  ResetProperties( bufferIndex );
919  }
920 
921  //Process the queued scene messages
922  mImpl->messageQueue.ProcessMessages( bufferIndex );
923 
924  //Post Process Ids of resources updated by renderer
926 
927  //Forward compiled shader programs to event thread for saving
929 
930  // Although the scene-graph may not require an update, we still need to synchronize double-buffered
931  // renderer lists if the scene was updated in the previous frame.
932  // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
933  if( updateScene || mImpl->previousUpdateScene )
934  {
935  //Animate
936  Animate( bufferIndex, elapsedSeconds );
937 
938  //Constraint custom objects
939  ConstrainCustomObjects( bufferIndex );
940 
941  //Prepare materials and apply constraints to them
942  PrepareMaterials( bufferIndex );
943 
944  //Clear the lists of renderable-attachments from the previous update
945  for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
946  {
947  mImpl->sortedLayers[i]->ClearRenderables();
948  }
949 
950  for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
951  {
952  mImpl->systemLevelSortedLayers[i]->ClearRenderables();
953  }
954 
955  //Update node hierarchy, apply constraints and perform sorting / culling.
956  //This will populate each Layer with a list of renderers which are ready.
957  UpdateNodes( bufferIndex );
958 
959  //Apply constraints to RenderTasks, shaders and geometries
960  ConstrainRenderTasks( bufferIndex );
961  ConstrainShaders( bufferIndex );
962  mImpl->geometries.ConstrainObjects( bufferIndex );
963 
964  //Update renderers and apply constraints
965  UpdateRenderers( bufferIndex );
966 
967  //Process Property Notifications
968  ProcessPropertyNotifications( bufferIndex );
969 
970  //Process the RenderTasks; this creates the instructions for rendering the next frame.
971  //reset the update buffer index and make sure there is enough room in the instruction container
974 
975  if ( NULL != mImpl->root )
976  {
977  ProcessRenderTasks( bufferIndex,
978  mImpl->taskList,
979  *mImpl->root,
983 
984  // Process the system-level RenderTasks last
985  if ( NULL != mImpl->systemLevelRoot )
986  {
987  ProcessRenderTasks( bufferIndex,
993  }
994  }
995  }
996 
997  // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
998  bool doRenderOnceNotify = false;
999  mImpl->renderTaskWaiting = false;
1001  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1002  endIter != iter; ++iter )
1003  {
1004  RenderTask& renderTask(*(*iter));
1005 
1006  renderTask.UpdateState();
1007 
1008  if( renderTask.IsWaitingToRender() &&
1009  renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1010  {
1011  mImpl->renderTaskWaiting = true; // keep update/render threads alive
1012  }
1013 
1014  if( renderTask.HasRendered() )
1015  {
1016  doRenderOnceNotify = true;
1017  }
1018  }
1019 
1020  if( doRenderOnceNotify )
1021  {
1022  DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1024  }
1025 
1026  // Macro is undefined in release build.
1028 
1029  // A ResetProperties() may be required in the next frame
1030  mImpl->previousUpdateScene = updateScene;
1031 
1032  // Check whether further updates are required
1033  unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1034 
1035  // tell the update manager that we're done so the queue can be given to event thread
1037 
1038  // The update has finished; swap the double-buffering indices
1040 
1041  return keepUpdating;
1042 }
1043 
1044 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1045 {
1046  // Update the duration set via Stage::KeepRendering()
1047  if ( mImpl->keepRenderingSeconds > 0.0f )
1048  {
1049  mImpl->keepRenderingSeconds -= elapsedSeconds;
1050  }
1051 
1052  unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1053 
1054  // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1055  // Keep updating until no messages are received and no animations are running.
1056  // If an animation has just finished, update at least once more for Discard end-actions.
1057  // No need to check for renderQueue as there is always a render after update and if that
1058  // render needs another update it will tell the adaptor to call update again
1059 
1060  if ( mImpl->keepRenderingSeconds > 0.0f )
1061  {
1062  keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1063  }
1064 
1065  if ( IsAnimationRunning() ||
1067  {
1068  keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1069  }
1070 
1071  if ( mImpl->renderTaskWaiting )
1072  {
1073  keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1074  }
1075 
1076  return keepUpdatingRequest;
1077 }
1078 
1080 {
1081  typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1082 
1083  // Reserve some memory inside the render queue
1084  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1085 
1086  // Construct message in the render queue memory; note that delete should not be called on the return value
1087  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1088 }
1089 
1091 {
1092  typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1093 
1094  // Reserve some memory inside the render queue
1095  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1096 
1097  // Construct message in the render queue memory; note that delete should not be called on the return value
1098  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1099 }
1100 
1101 void UpdateManager::KeepRendering( float durationSeconds )
1102 {
1103  mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1104 }
1105 
1106 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1107 {
1108  if ( !systemLevel )
1109  {
1110  // just copy the vector of pointers
1111  mImpl->sortedLayers = layers;
1112  }
1113  else
1114  {
1115  mImpl->systemLevelSortedLayers = layers;
1116  }
1117 }
1118 
1120 {
1121  mImpl->shaderSaver = &upstream;
1122 }
1123 
1125 {
1127 
1128  // Reserve some memory inside the render queue
1129  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1130 
1131  // Construct message in the render queue memory; note that delete should not be called on the return value
1132  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1133 }
1134 
1136 {
1138 
1139  // Reserve some memory inside the render queue
1140  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1141 
1142  // Construct message in the render queue memory; note that delete should not be called on the return value
1143  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1144 }
1145 
1146 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1147 {
1149 
1150  // Reserve some memory inside the render queue
1151  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1152 
1153  // Construct message in the render queue memory; note that delete should not be called on the return value
1154  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1155 }
1156 
1157 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int uWrapMode, unsigned int vWrapMode )
1158 {
1160 
1161  // Reserve some memory inside the render queue
1162  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1163 
1164  // Construct message in the render queue memory; note that delete should not be called on the return value
1165  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, uWrapMode, vWrapMode );
1166 }
1167 
1169 {
1171 
1172  // Reserve some memory inside the render queue
1173  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1174 
1175  // Construct message in the render queue memory; note that delete should not be called on the return value
1176  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1177 }
1178 
1180 {
1182 
1183  // Reserve some memory inside the render queue
1184  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1185 
1186  // Construct message in the render queue memory; note that delete should not be called on the return value
1187  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1188 }
1189 
1191 {
1193 
1194  // Reserve some memory inside the render queue
1195  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1196 
1197  // Construct message in the render queue memory; note that delete should not be called on the return value
1198  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1199 }
1200 
1202 {
1204 
1205  // Reserve some memory inside the render queue
1206  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1207 
1208  // Construct message in the render queue memory; note that delete should not be called on the return value
1209  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data );
1210 }
1211 
1213 {
1215 
1216  // Reserve some memory inside the render queue
1217  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1218 
1219  // Construct message in the render queue memory; note that delete should not be called on the return value
1220  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferSize, propertyBuffer, size );
1221 }
1222 
1223 } // namespace SceneGraph
1224 
1225 } // namespace Internal
1226 
1227 } // namespace Dali
Dali Docs Home
Read more about Dali