[dali_1.3.40] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-manager.cpp
index 64bf05f..10f290f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@
 #include <dali/internal/update/controllers/render-message-dispatcher.h>
 #include <dali/internal/update/controllers/scene-controller-impl.h>
 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+#include <dali/internal/update/manager/frame-callback-processor.h>
 #include <dali/internal/update/manager/render-task-processor.h>
 #include <dali/internal/update/manager/sorted-layers.h>
 #include <dali/internal/update/manager/update-algorithms.h>
@@ -108,11 +109,10 @@ template< class T >
 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
 {
   // Reset animatable properties to base values
-  typename OwnerContainer<T*>::Iterator iter = container.Begin();
-  const typename OwnerContainer<T*>::ConstIterator endIter = container.End();
-  for ( ; iter != endIter; ++iter )
+  // use reference to avoid extra copies of the iterator
+  for( auto&& iter : container )
   {
-    (*iter)->ResetToBaseValues( updateBufferIndex );
+    iter->ResetToBaseValues( updateBufferIndex );
   }
 }
 
@@ -128,33 +128,36 @@ inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, Di
 {
   DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
 
-  typename OwnerContainer<T*>::Iterator iter = container.Begin();
-  const typename OwnerContainer<T*>::ConstIterator endIter = container.End();
-  for ( ; iter != endIter; ++iter )
+  // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
+  for( auto&& iter : container )
   {
-    if ( *iter == object )
+    if ( iter == object )
     {
       // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
-      discardQueue.Add( updateBufferIndex, container.Release( iter ) );
-      return;
+      discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
+      return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
     }
   }
 }
 
-}
-
-typedef OwnerContainer< Shader* >              ShaderOwner;
-typedef ShaderOwner::Iterator                  ShaderIter;
-typedef std::vector<Internal::ShaderDataPtr>   ShaderDataBinaryQueue;
-
-typedef OwnerContainer< TextureSet* >          TextureSetOwner;
-typedef TextureSetOwner::Iterator              TextureSetIter;
+/**
+ * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
+ * @param[in] node The node whose hierarchy to descend
+ */
+void SortSiblingNodesRecursively( Node& node )
+{
+  NodeContainer& container = node.GetChildren();
+  std::sort( container.Begin(), container.End(),
+             []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
 
-typedef OwnerContainer<Renderer*>              RendererOwner;
-typedef RendererOwner::Iterator                RendererIter;
+  // Descend tree and sort as well
+  for( auto&& iter : container )
+  {
+    SortSiblingNodesRecursively( *iter );
+  }
+}
 
-typedef OwnerContainer< Camera* >              CameraOwner;
-typedef OwnerContainer< PropertyOwner* >       CustomObjectOwner;
+} // unnamed namespace
 
 /**
  * Structure to contain UpdateManager internal data
@@ -193,13 +196,16 @@ struct UpdateManager::Impl
     shaders(),
     panGestureProcessor( NULL ),
     messageQueue( renderController, sceneGraphBuffers ),
+    frameCallbackProcessor( NULL ),
     keepRenderingSeconds( 0.0f ),
     nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
     frameCounter( 0 ),
+    renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
     animationFinishedDuringUpdate( false ),
     previousUpdateScene( false ),
     renderTaskWaiting( false ),
-    renderersAdded( false )
+    renderersAdded( false ),
+    surfaceRectChanged( false )
   {
     sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
 
@@ -211,15 +217,15 @@ struct UpdateManager::Impl
   {
     // Disconnect render tasks from nodes, before destroying the nodes
     RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
-    for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
+    for ( auto&& iter : tasks )
     {
-      (*iter)->SetSourceNode( NULL );
+      iter->SetSourceNode( NULL );
     }
     // ..repeat for system level RenderTasks
     RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
-    for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
+    for ( auto&& iter : systemLevelTasks )
     {
-      (*iter)->SetSourceNode( NULL );
+      iter->SetSourceNode( NULL );
     }
 
     // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
@@ -252,58 +258,75 @@ struct UpdateManager::Impl
     delete sceneController;
   }
 
-  SceneGraphBuffers                   sceneGraphBuffers;             ///< Used to keep track of which buffers are being written or read
-  RenderMessageDispatcher             renderMessageDispatcher;       ///< Used for passing messages to the render-thread
-  NotificationManager&                notificationManager;           ///< Queues notification messages for the event-thread.
-  TransformManager                    transformManager;              ///< Used to update the transformation matrices of the nodes
-  CompleteNotificationInterface&      animationPlaylist;             ///< Holds handles to all the animations
-  PropertyNotifier&                   propertyNotifier;              ///< Provides notification to applications when properties are modified.
-  ShaderSaver*                        shaderSaver;                   ///< Saves shader binaries.
-  DiscardQueue&                       discardQueue;                  ///< Nodes are added here when disconnected from the scene-graph.
-  RenderController&                   renderController;              ///< render controller
-  SceneControllerImpl*                sceneController;               ///< scene controller
-  RenderManager&                      renderManager;                 ///< This is responsible for rendering the results of each "update"
-  RenderQueue&                        renderQueue;                   ///< Used to queue messages for the next render
-  RenderInstructionContainer&         renderInstructions;            ///< Used to prepare the render instructions
-  RenderTaskProcessor&                renderTaskProcessor;           ///< Handles RenderTasks and RenderInstrucitons
+  /**
+   * Lazy init for FrameCallbackProcessor.
+   */
+  FrameCallbackProcessor& GetFrameCallbackProcessor()
+  {
+    if( ! frameCallbackProcessor )
+    {
+      frameCallbackProcessor = new FrameCallbackProcessor( transformManager, *root );
+    }
+    return *frameCallbackProcessor;
+  }
 
-  Vector4                             backgroundColor;               ///< The glClear color used at the beginning of each frame.
+  SceneGraphBuffers                    sceneGraphBuffers;             ///< Used to keep track of which buffers are being written or read
+  RenderMessageDispatcher              renderMessageDispatcher;       ///< Used for passing messages to the render-thread
+  NotificationManager&                 notificationManager;           ///< Queues notification messages for the event-thread.
+  TransformManager                     transformManager;              ///< Used to update the transformation matrices of the nodes
+  CompleteNotificationInterface&       animationPlaylist;             ///< Holds handles to all the animations
+  PropertyNotifier&                    propertyNotifier;              ///< Provides notification to applications when properties are modified.
+  ShaderSaver*                         shaderSaver;                   ///< Saves shader binaries.
+  DiscardQueue&                        discardQueue;                  ///< Nodes are added here when disconnected from the scene-graph.
+  RenderController&                    renderController;              ///< render controller
+  SceneControllerImpl*                 sceneController;               ///< scene controller
+  RenderManager&                       renderManager;                 ///< This is responsible for rendering the results of each "update"
+  RenderQueue&                         renderQueue;                   ///< Used to queue messages for the next render
+  RenderInstructionContainer&          renderInstructions;            ///< Used to prepare the render instructions
+  RenderTaskProcessor&                 renderTaskProcessor;           ///< Handles RenderTasks and RenderInstrucitons
 
-  RenderTaskList                      taskList;                      ///< The list of scene graph render-tasks
-  RenderTaskList                      systemLevelTaskList;           ///< Separate render-tasks for system-level content
+  Vector4                              backgroundColor;               ///< The glClear color used at the beginning of each frame.
 
-  Layer*                              root;                          ///< The root node (root is a layer)
-  Layer*                              systemLevelRoot;               ///< A separate root-node for system-level content
+  RenderTaskList                       taskList;                      ///< The list of scene graph render-tasks
+  RenderTaskList                       systemLevelTaskList;           ///< Separate render-tasks for system-level content
 
-  Vector<Node*>                       nodes;                         ///< A container of all instantiated nodes
+  Layer*                               root;                          ///< The root node (root is a layer)
+  Layer*                               systemLevelRoot;               ///< A separate root-node for system-level content
 
-  SortedLayerPointers                 sortedLayers;                  ///< A container of Layer pointers sorted by depth
-  SortedLayerPointers                 systemLevelSortedLayers;       ///< A separate container of system-level Layers
+  Vector<Node*>                        nodes;                         ///< A container of all instantiated nodes
 
-  CameraOwner                         cameras;                       ///< A container of cameras
-  CustomObjectOwner                   customObjects;                 ///< A container of owned objects (with custom properties)
+  SortedLayerPointers                  sortedLayers;                  ///< A container of Layer pointers sorted by depth
+  SortedLayerPointers                  systemLevelSortedLayers;       ///< A separate container of system-level Layers
 
-  AnimationContainer                  animations;                    ///< A container of owned animations
-  PropertyNotificationContainer       propertyNotifications;         ///< A container of owner property notifications.
+  OwnerContainer< Camera* >            cameras;                       ///< A container of cameras
+  OwnerContainer< PropertyOwner* >     customObjects;                 ///< A container of owned objects (with custom properties)
 
-  RendererOwner                       renderers;                     ///< A container of owned renderers
-  TextureSetOwner                     textureSets;                   ///< A container of owned texture sets
-  ShaderOwner                         shaders;                       ///< A container of owned shaders
-  OwnerPointer<PanGesture>            panGestureProcessor;           ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
+  OwnerContainer< PropertyResetterBase* > propertyResetters;          ///< A container of property resetters
+  AnimationContainer                   animations;                    ///< A container of owned animations
+  PropertyNotificationContainer        propertyNotifications;         ///< A container of owner property notifications.
+  OwnerContainer< Renderer* >          renderers;                     ///< A container of owned renderers
+  OwnerContainer< TextureSet* >        textureSets;                   ///< A container of owned texture sets
+  OwnerContainer< Shader* >            shaders;                       ///< A container of owned shaders
+  OwnerPointer< PanGesture >           panGestureProcessor;           ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
 
-  MessageQueue                        messageQueue;                  ///< The messages queued from the event-thread
-  ShaderDataBinaryQueue               renderCompiledShaders;         ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
-  ShaderDataBinaryQueue               updateCompiledShaders;         ///< Shaders to be sent from Update to Event
-  Mutex                               compiledShaderMutex;           ///< lock to ensure no corruption on the renderCompiledShaders
+  MessageQueue                         messageQueue;                  ///< The messages queued from the event-thread
+  std::vector<Internal::ShaderDataPtr> renderCompiledShaders;         ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
+  std::vector<Internal::ShaderDataPtr> updateCompiledShaders;         ///< Shaders to be sent from Update to Event
+  Mutex                                compiledShaderMutex;           ///< lock to ensure no corruption on the renderCompiledShaders
 
-  float                               keepRenderingSeconds;          ///< Set via Dali::Stage::KeepRendering
-  int                                 nodeDirtyFlags;                ///< cumulative node dirty flags from previous frame
-  int                                 frameCounter;                  ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
+  OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor;        ///< Owned FrameCallbackProcessor, only created if required.
 
-  bool                                animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
-  bool                                previousUpdateScene;           ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
-  bool                                renderTaskWaiting;             ///< A REFRESH_ONCE render task is waiting to be rendered
-  bool                                renderersAdded;                ///< Flag to keep track when renderers have been added to avoid unnecessary processing
+  float                                keepRenderingSeconds;          ///< Set via Dali::Stage::KeepRendering
+  int                                  nodeDirtyFlags;                ///< cumulative node dirty flags from previous frame
+  int                                  frameCounter;                  ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
+
+  DevelStage::Rendering                renderingBehavior;             ///< Set via DevelStage::SetRenderingBehavior
+
+  bool                                 animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
+  bool                                 previousUpdateScene;           ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
+  bool                                 renderTaskWaiting;             ///< A REFRESH_ONCE render task is waiting to be rendered
+  bool                                 renderersAdded;                ///< Flag to keep track when renderers have been added to avoid unnecessary processing
+  bool                                 surfaceRectChanged;            ///< True if the default surface rect is changed
 
 private:
 
@@ -464,24 +487,25 @@ void UpdateManager::RemoveAnimation( Animation* animation )
 
 bool UpdateManager::IsAnimationRunning() const
 {
-  bool isRunning(false);
-  AnimationContainer& animations = mImpl->animations;
-
   // Find any animation that isn't stopped or paused
-
-  const AnimationIter endIter = animations.End();
-  for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
+  for ( auto&& iter : mImpl->animations )
   {
-    const Animation::State state = (*iter)->GetState();
+    const Animation::State state = iter->GetState();
 
     if (state != Animation::Stopped &&
         state != Animation::Paused)
     {
-      isRunning = true;
+      return true; // stop iteration as soon as first one is found
     }
   }
 
-  return isRunning;
+  return false;
+}
+
+void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
+{
+  propertyResetter->Initialize();
+  mImpl->propertyResetters.PushBack( propertyResetter.Release() );
 }
 
 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
@@ -609,40 +633,30 @@ void UpdateManager::ResetProperties( BufferIndex bufferIndex )
   // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
   mImpl->animationFinishedDuringUpdate = false;
 
-  // Animated properties have to be reset to their original value each frame
-
-  // Reset root properties
-  if ( mImpl->root )
+  // Reset all animating / constrained properties
+  std::vector<PropertyResetterBase*>toDelete;
+  for( auto&& element : mImpl->propertyResetters )
   {
-    mImpl->root->ResetToBaseValues( bufferIndex );
+    element->ResetToBaseValue( bufferIndex );
+    if( element->IsFinished() )
+    {
+      toDelete.push_back( element );
+    }
   }
-  if ( mImpl->systemLevelRoot )
+
+  // If a resetter is no longer required (the animator or constraint has been removed), delete it.
+  for( auto&& elementPtr : toDelete )
   {
-    mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
+    mImpl->propertyResetters.EraseObject( elementPtr );
   }
 
-  // Reset all the nodes
+  // Clear node dirty flags
   Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
   Vector<Node*>::Iterator endIter = mImpl->nodes.End();
   for( ;iter != endIter; ++iter )
   {
-    (*iter)->ResetToBaseValues( bufferIndex );
+    (*iter)->ResetDirtyFlags( bufferIndex );
   }
-
-  // Reset system-level render-task list properties to base values
-  ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
-
-  // Reset render-task list properties to base values.
-  ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
-
-  // Reset custom object properties to base values
-  ResetToBaseValues( mImpl->customObjects, bufferIndex );
-
-  // Reset animatable renderer properties to base values
-  ResetToBaseValues( mImpl->renderers, bufferIndex );
-
-  // Reset animatable shader properties to base values
-  ResetToBaseValues( mImpl->shaders, bufferIndex );
 }
 
 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
@@ -703,12 +717,9 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
 {
   //Constrain custom objects (in construction order)
-  OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
-  const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
-  for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
+  for ( auto&& object : mImpl->customObjects )
   {
-    PropertyOwner& object = **iter;
-    ConstrainPropertyOwner( object, bufferIndex );
+    ConstrainPropertyOwner( *object, bufferIndex );
   }
 }
 
@@ -716,46 +727,37 @@ void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
 {
   // Constrain system-level render-tasks
   const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
-  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
+  for ( auto&& task : systemLevelTasks )
   {
-    RenderTask& task = **iter;
-    ConstrainPropertyOwner( task, bufferIndex );
+    ConstrainPropertyOwner( *task, bufferIndex );
   }
 
   // Constrain render-tasks
   const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
-  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
+  for ( auto&& task : tasks )
   {
-    RenderTask& task = **iter;
-    ConstrainPropertyOwner( task, bufferIndex );
+    ConstrainPropertyOwner( *task, bufferIndex );
   }
 }
 
 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
 {
   // constrain shaders... (in construction order)
-  ShaderOwner& shaders = mImpl->shaders;
-  for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
+  for ( auto&& shader : mImpl->shaders )
   {
-    Shader& shader = **iter;
-    ConstrainPropertyOwner( shader, bufferIndex );
+    ConstrainPropertyOwner( *shader, bufferIndex );
   }
 }
 
 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
 {
-  PropertyNotificationContainer &notifications = mImpl->propertyNotifications;
-  PropertyNotificationIter iter = notifications.Begin();
-
-  while ( iter != notifications.End() )
+  for( auto&& notification : mImpl->propertyNotifications )
   {
-    PropertyNotification* notification = *iter;
     bool valid = notification->Check( bufferIndex );
     if(valid)
     {
       mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
     }
-    ++iter;
   }
 }
 
@@ -774,11 +776,9 @@ void UpdateManager::ForwardCompiledShadersToEventThread()
     if( mImpl->updateCompiledShaders.size() > 0 )
     {
       ShaderSaver& factory = *mImpl->shaderSaver;
-      ShaderDataBinaryQueue::iterator i   = mImpl->updateCompiledShaders.begin();
-      ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
-      for( ; i != end; ++i )
+      for( auto&& shader : mImpl->updateCompiledShaders )
       {
-        mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
+        mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
       }
       // we don't need them in update anymore
       mImpl->updateCompiledShaders.clear();
@@ -823,7 +823,9 @@ void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
 
 unsigned int UpdateManager::Update( float elapsedSeconds,
                                     unsigned int lastVSyncTimeMilliseconds,
-                                    unsigned int nextVSyncTimeMilliseconds )
+                                    unsigned int nextVSyncTimeMilliseconds,
+                                    bool renderToFboEnabled,
+                                    bool isRenderingToFbo )
 {
   const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
 
@@ -890,17 +892,22 @@ unsigned int UpdateManager::Update( float elapsedSeconds,
     //Update renderers and apply constraints
     UpdateRenderers( bufferIndex );
 
-    //Update the trnasformations of all the nodes
+    //Update the transformations of all the nodes
     mImpl->transformManager.Update();
 
+    // Call the frame-callback-processor if set
+    if( mImpl->frameCallbackProcessor )
+    {
+      mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
+    }
+
     //Process Property Notifications
     ProcessPropertyNotifications( bufferIndex );
 
     //Update cameras
-    const CameraOwner::Iterator endCameraIterator = mImpl->cameras.End();
-    for( CameraOwner::Iterator cameraIterator = mImpl->cameras.Begin(); endCameraIterator != cameraIterator; ++cameraIterator )
+    for( auto&& cameraIterator : mImpl->cameras )
     {
-      ( *cameraIterator )->Update( bufferIndex );
+      cameraIterator->Update( bufferIndex );
     }
 
     //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
@@ -913,19 +920,23 @@ unsigned int UpdateManager::Update( float elapsedSeconds,
       if ( NULL != mImpl->root )
       {
         mImpl->renderTaskProcessor.Process( bufferIndex,
-                                          mImpl->taskList,
-                                          *mImpl->root,
-                                          mImpl->sortedLayers,
-                                          mImpl->renderInstructions );
+                                            mImpl->taskList,
+                                            *mImpl->root,
+                                            mImpl->sortedLayers,
+                                            mImpl->renderInstructions,
+                                            renderToFboEnabled,
+                                            isRenderingToFbo );
 
         // Process the system-level RenderTasks last
         if ( NULL != mImpl->systemLevelRoot )
         {
           mImpl->renderTaskProcessor.Process( bufferIndex,
-                                            mImpl->systemLevelTaskList,
-                                            *mImpl->systemLevelRoot,
-                                            mImpl->systemLevelSortedLayers,
-                                            mImpl->renderInstructions );
+                                              mImpl->systemLevelTaskList,
+                                              *mImpl->systemLevelRoot,
+                                              mImpl->systemLevelSortedLayers,
+                                              mImpl->renderInstructions,
+                                              renderToFboEnabled,
+                                              isRenderingToFbo );
         }
       }
     }
@@ -934,21 +945,17 @@ unsigned int UpdateManager::Update( float elapsedSeconds,
   // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
   bool doRenderOnceNotify = false;
   mImpl->renderTaskWaiting = false;
-  const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
-  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
-        endIter != iter; ++iter )
+  for ( auto&& renderTask : mImpl->taskList.GetTasks() )
   {
-    RenderTask& renderTask(*(*iter));
+    renderTask->UpdateState();
 
-    renderTask.UpdateState();
-
-    if( renderTask.IsWaitingToRender() &&
-        renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
+    if( renderTask->IsWaitingToRender() &&
+        renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
     {
       mImpl->renderTaskWaiting = true; // keep update/render threads alive
     }
 
-    if( renderTask.HasRendered() )
+    if( renderTask->HasRendered() )
     {
       doRenderOnceNotify = true;
     }
@@ -988,13 +995,15 @@ unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
 
   unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
 
+  // If the rendering behavior is set to continuously render, then continue to render.
   // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
   // Keep updating until no messages are received and no animations are running.
   // If an animation has just finished, update at least once more for Discard end-actions.
   // No need to check for renderQueue as there is always a render after update and if that
   // render needs another update it will tell the adaptor to call update again
 
-  if ( mImpl->keepRenderingSeconds > 0.0f )
+  if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
+       ( mImpl->keepRenderingSeconds > 0.0f ) )
   {
     keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
   }
@@ -1026,6 +1035,8 @@ void UpdateManager::SetBackgroundColor( const Vector4& color )
 
 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
 {
+  mImpl->surfaceRectChanged = true;
+
   typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
 
   // Reserve some memory inside the render queue
@@ -1040,6 +1051,11 @@ void UpdateManager::KeepRendering( float durationSeconds )
   mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
 }
 
+void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
+{
+  mImpl->renderingBehavior = renderingBehavior;
+}
+
 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
 {
   if ( !systemLevel )
@@ -1057,12 +1073,33 @@ void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
 {
   // note,this vector is already in depth order. It could be used as-is to
   // remove sorting in update algorithm. However, it lacks layer boundary markers.
-  for( std::vector<NodeDepthPair>::iterator iter = nodeDepths->nodeDepths.begin(),
-         end = nodeDepths->nodeDepths.end() ;
-       iter != end ; ++iter )
+  for( auto&& iter : nodeDepths->nodeDepths )
   {
-    iter->node->SetDepthIndex( iter->sortedDepth );
+    iter.node->SetDepthIndex( iter.sortedDepth );
   }
+
+  // Go through node hierarchy and rearrange siblings according to depth-index
+  SortSiblingNodesRecursively( *( mImpl->root ) );
+}
+
+bool UpdateManager::IsDefaultSurfaceRectChanged()
+{
+  bool surfaceRectChanged = mImpl->surfaceRectChanged;
+
+  // Reset the flag
+  mImpl->surfaceRectChanged = false;
+
+  return surfaceRectChanged;
+}
+
+void UpdateManager::AddFrameCallback( FrameCallbackInterface* frameCallback, const Node* rootNode )
+{
+  mImpl->GetFrameCallbackProcessor().AddFrameCallback( frameCallback, rootNode );
+}
+
+void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
+{
+  mImpl->GetFrameCallbackProcessor().RemoveFrameCallback( frameCallback );
 }
 
 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )