[Tizen] Add screen and client rotation itself function
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-manager.cpp
index f8df0f4..ce30100 100644 (file)
@@ -167,10 +167,10 @@ struct UpdateManager::Impl
     transformManager(),
     animationPlaylist( animationPlaylist ),
     propertyNotifier( propertyNotifier ),
-    shaderSaver( NULL ),
+    shaderSaver( nullptr ),
     discardQueue( discardQueue ),
     renderController( renderController ),
-    sceneController( NULL ),
+    sceneController( nullptr ),
     renderManager( renderManager ),
     renderQueue( renderQueue ),
     renderTaskProcessor( renderTaskProcessor ),
@@ -178,9 +178,9 @@ struct UpdateManager::Impl
     renderers(),
     textureSets(),
     shaders(),
-    panGestureProcessor( NULL ),
+    panGestureProcessor( nullptr ),
     messageQueue( renderController, sceneGraphBuffers ),
-    frameCallbackProcessor( NULL ),
+    frameCallbackProcessor( nullptr ),
     keepRenderingSeconds( 0.0f ),
     nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
     frameCounter( 0 ),
@@ -189,12 +189,13 @@ struct UpdateManager::Impl
     previousUpdateScene( false ),
     renderTaskWaiting( false ),
     renderersAdded( false ),
-    surfaceRectChanged( false )
+    surfaceRectChanged( false ),
+    renderingRequired( false )
   {
     sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
 
     // create first 'dummy' node
-    nodes.PushBack(0u);
+    nodes.PushBack(nullptr);
   }
 
   ~Impl()
@@ -207,7 +208,7 @@ struct UpdateManager::Impl
         RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
         for ( auto&& task : tasks )
         {
-          task->SetSourceNode( NULL );
+          task->SetSourceNode( nullptr );
         }
       }
     }
@@ -298,6 +299,7 @@ struct UpdateManager::Impl
   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
+  bool                                 renderingRequired;             ///< True if required to render the current frame
 
 private:
 
@@ -313,7 +315,7 @@ UpdateManager::UpdateManager( NotificationManager& notificationManager,
                               RenderManager& renderManager,
                               RenderQueue& renderQueue,
                               RenderTaskProcessor& renderTaskProcessor )
-  : mImpl(NULL)
+  : mImpl(nullptr)
 {
   mImpl = new Impl( notificationManager,
                     animationFinishedNotifier,
@@ -374,7 +376,7 @@ void UpdateManager::UninstallRoot( Layer* layer )
 
 void UpdateManager::AddNode( OwnerPointer<Node>& node )
 {
-  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
+  DALI_ASSERT_ALWAYS( nullptr == node->GetParent() ); // Should not have a parent yet
 
   // Nodes must be sorted by pointer
   Node* rawNode = node.Release();
@@ -394,9 +396,9 @@ void UpdateManager::AddNode( OwnerPointer<Node>& node )
 
 void UpdateManager::ConnectNode( Node* parent, Node* node )
 {
-  DALI_ASSERT_ALWAYS( NULL != parent );
-  DALI_ASSERT_ALWAYS( NULL != node );
-  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
+  DALI_ASSERT_ALWAYS( nullptr != parent );
+  DALI_ASSERT_ALWAYS( nullptr != node );
+  DALI_ASSERT_ALWAYS( nullptr == node->GetParent() ); // Should not have a parent yet
 
   DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] ConnectNode\n", node );
 
@@ -414,7 +416,7 @@ void UpdateManager::DisconnectNode( Node* node )
   DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DisconnectNode\n", node );
 
   Node* parent = node->GetParent();
-  DALI_ASSERT_ALWAYS( NULL != parent );
+  DALI_ASSERT_ALWAYS( nullptr != parent );
   parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
 
   parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
@@ -428,8 +430,8 @@ void UpdateManager::DisconnectNode( Node* node )
 
 void UpdateManager::DestroyNode( Node* node )
 {
-  DALI_ASSERT_ALWAYS( NULL != node );
-  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
+  DALI_ASSERT_ALWAYS( nullptr != node );
+  DALI_ASSERT_ALWAYS( nullptr == node->GetParent() ); // Should have been disconnected
 
   DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DestroyNode\n", node );
 
@@ -734,8 +736,10 @@ bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSync
   return gestureUpdated;
 }
 
-void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
+bool UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
 {
+  bool animationActive = false;
+
   auto&& iter = mImpl->animations.Begin();
   bool animationLooped = false;
 
@@ -747,6 +751,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
     bool progressMarkerReached = false;
     animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
 
+    animationActive = animationActive || animation->IsActive();
+
     if ( progressMarkerReached )
     {
       mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
@@ -772,6 +778,8 @@ void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
     // The application should be notified by NotificationManager, in another thread
     mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
   }
+
+  return animationActive;
 }
 
 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
@@ -852,7 +860,7 @@ void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
     //Apply constraints
     ConstrainPropertyOwner( *renderer, bufferIndex );
 
-    renderer->PrepareRender( bufferIndex );
+    mImpl->renderingRequired = renderer->PrepareRender( bufferIndex ) || mImpl->renderingRequired;
   }
 }
 
@@ -884,17 +892,20 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
   //Clear nodes/resources which were previously discarded
   mImpl->discardQueue.Clear( bufferIndex );
 
+  bool isAnimationRunning = IsAnimationRunning();
+
   //Process Touches & Gestures
   const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
 
   bool updateScene = // The scene-graph requires an update if..
       (mImpl->nodeDirtyFlags & RenderableUpdateFlags) ||    // ..nodes were dirty in previous frame OR
-      IsAnimationRunning()                            ||    // ..at least one animation is running OR
+      isAnimationRunning                              ||    // ..at least one animation is running OR
       mImpl->messageQueue.IsSceneUpdateRequired()     ||    // ..a message that modifies the scene graph node tree is queued OR
       mImpl->frameCallbackProcessor                   ||    // ..a frame callback processor is existed OR
       gestureUpdated;                                       // ..a gesture property was updated
 
   bool keepRendererRendering = false;
+  mImpl->renderingRequired = false;
 
   // Although the scene-graph may not require an update, we still need to synchronize double-buffered
   // values if the scene was updated in the previous frame.
@@ -919,7 +930,7 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
   if( updateScene || mImpl->previousUpdateScene )
   {
     //Animate
-    Animate( bufferIndex, elapsedSeconds );
+    bool animationActive = Animate( bufferIndex, elapsedSeconds );
 
     //Constraint custom objects
     ConstrainCustomObjects( bufferIndex );
@@ -957,7 +968,10 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
     UpdateRenderers( bufferIndex );
 
     //Update the transformations of all the nodes
-    mImpl->transformManager.Update();
+    if ( mImpl->transformManager.Update() )
+    {
+      mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM;
+    }
 
     //Process Property Notifications
     ProcessPropertyNotifications( bufferIndex );
@@ -982,7 +996,6 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
         }
       }
 
-
       std::size_t numberOfRenderInstructions = 0;
       for ( auto&& scene : mImpl->scenes )
       {
@@ -991,13 +1004,19 @@ uint32_t UpdateManager::Update( float elapsedSeconds,
           scene->scene->GetRenderInstructions().ResetAndReserve( bufferIndex,
                                                      static_cast<uint32_t>( scene->taskList->GetTasks().Count() ) );
 
-          keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
-                                              *scene->taskList,
-                                              *scene->root,
-                                              scene->sortedLayerList,
-                                              scene->scene->GetRenderInstructions(),
-                                              renderToFboEnabled,
-                                              isRenderingToFbo );
+          // If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed)
+          // or the nodes are dirty
+          if ( !isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) )
+          {
+            keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
+                                                *scene->taskList,
+                                                *scene->root,
+                                                scene->sortedLayerList,
+                                                scene->scene->GetRenderInstructions(),
+                                                renderToFboEnabled,
+                                                isRenderingToFbo );
+
+          }
 
           numberOfRenderInstructions += scene->scene->GetRenderInstructions().Count( bufferIndex );
         }
@@ -1129,6 +1148,17 @@ void UpdateManager::SurfaceReplaced( Scene* scene )
   new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::SurfaceReplaced, scene );
 }
 
+void UpdateManager::SetDefaultSurfaceOrientation( int orientation )
+{
+  typedef MessageValue1< RenderManager, int > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::SetDefaultSurfaceOrientation, orientation );
+}
+
 void UpdateManager::KeepRendering( float durationSeconds )
 {
   mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
@@ -1139,6 +1169,11 @@ void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavio
   mImpl->renderingBehavior = renderingBehavior;
 }
 
+void UpdateManager::RequestRendering()
+{
+  mImpl->renderingRequired = true;
+}
+
 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
 {
   for ( auto&& scene : mImpl->scenes )