[Tizen] Revert "Support screen rotation"
[platform/core/uifw/dali-adaptor.git] / adaptors / base / combined-update-render / combined-update-render-controller.cpp
index 26af651..715053f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 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.
@@ -55,8 +55,8 @@ const unsigned int NANOSECONDS_PER_MILLISECOND( 1e+6 );
 
 // The following values will get calculated at compile time
 const float        DEFAULT_FRAME_DURATION_IN_SECONDS( 1.0f / 60.0f );
-const unsigned int DEFAULT_FRAME_DURATION_IN_MILLISECONDS( DEFAULT_FRAME_DURATION_IN_SECONDS * MILLISECONDS_PER_SECOND );
-const unsigned int DEFAULT_FRAME_DURATION_IN_NANOSECONDS( DEFAULT_FRAME_DURATION_IN_SECONDS * NANOSECONDS_PER_SECOND );
+const uint64_t DEFAULT_FRAME_DURATION_IN_MILLISECONDS( DEFAULT_FRAME_DURATION_IN_SECONDS * MILLISECONDS_PER_SECOND );
+const uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS( DEFAULT_FRAME_DURATION_IN_SECONDS * NANOSECONDS_PER_SECOND );
 
 /**
  * Handles the use case when an update-request is received JUST before we process a sleep-request. If we did not have an update-request count then
@@ -246,6 +246,12 @@ void CombinedUpdateRenderController::RequestUpdate()
 
 void CombinedUpdateRenderController::RequestUpdateOnce()
 {
+  // Increment the update-request count to the maximum
+  if( mUpdateRequestCount < MAXIMUM_UPDATE_REQUESTS )
+  {
+    ++mUpdateRequestCount;
+  }
+
   if( IsUpdateRenderThreadPaused() )
   {
     LOG_EVENT_TRACE;
@@ -282,9 +288,9 @@ void CombinedUpdateRenderController::SetRenderRefreshRate( unsigned int numberOf
 {
   // Not protected by lock, but written to rarely so not worth adding a lock when reading
   mDefaultFrameDelta                  = numberOfFramesPerRender * DEFAULT_FRAME_DURATION_IN_SECONDS;
-  mDefaultFrameDurationMilliseconds   = (uint64_t)numberOfFramesPerRender * DEFAULT_FRAME_DURATION_IN_MILLISECONDS;
-  mDefaultFrameDurationNanoseconds    = (uint64_t)numberOfFramesPerRender * DEFAULT_FRAME_DURATION_IN_NANOSECONDS;
-  mDefaultHalfFrameNanoseconds        = mDefaultFrameDurationNanoseconds / 2;
+  mDefaultFrameDurationMilliseconds   = uint64_t( numberOfFramesPerRender ) * DEFAULT_FRAME_DURATION_IN_MILLISECONDS;
+  mDefaultFrameDurationNanoseconds    = uint64_t( numberOfFramesPerRender ) * DEFAULT_FRAME_DURATION_IN_NANOSECONDS;
+  mDefaultHalfFrameNanoseconds        = mDefaultFrameDurationNanoseconds / 2u;
 
   LOG_EVENT( "mDefaultFrameDelta(%.6f), mDefaultFrameDurationMilliseconds(%lld), mDefaultFrameDurationNanoseconds(%lld)", mDefaultFrameDelta, mDefaultFrameDurationMilliseconds, mDefaultFrameDurationNanoseconds );
 }
@@ -370,8 +376,10 @@ void CombinedUpdateRenderController::UpdateRenderThread()
 
   bool useElapsedTime = true;
   bool updateRequired = true;
+  uint64_t timeToSleepUntil = 0;
+  int extraFramesDropped = 0;
 
-  while( UpdateRenderReady( useElapsedTime, updateRequired ) )
+  while( UpdateRenderReady( useElapsedTime, updateRequired, timeToSleepUntil ) )
   {
     LOG_UPDATE_RENDER_TRACE;
 
@@ -416,8 +424,8 @@ void CombinedUpdateRenderController::UpdateRenderThread()
     if( useElapsedTime )
     {
       // If using the elapsed time, then calculate frameDelta as a multiple of mDefaultFrameDelta
-      // Round up if remainder is more than half the default frame time
-      noOfFramesSinceLastUpdate = ( timeSinceLastFrame + mDefaultHalfFrameNanoseconds) / mDefaultFrameDurationNanoseconds;
+      noOfFramesSinceLastUpdate += extraFramesDropped;
+
       frameDelta = mDefaultFrameDelta * noOfFramesSinceLastUpdate;
     }
     LOG_UPDATE_RENDER( "timeSinceLastFrame(%llu) noOfFramesSinceLastUpdate(%u) frameDelta(%.6f)", timeSinceLastFrame, noOfFramesSinceLastUpdate, frameDelta );
@@ -453,7 +461,10 @@ void CombinedUpdateRenderController::UpdateRenderThread()
     mCore.Render( renderStatus );
     AddPerformanceMarker( PerformanceInterface::RENDER_END );
 
-    mRenderHelper.PostRender();
+    if( renderStatus.NeedsPostRender() )
+    {
+      mRenderHelper.PostRender();
+    }
 
     // Trigger event thread to request Update/Render thread to sleep if update not required
     if( ( Integration::KeepUpdating::NOT_REQUESTED == keepUpdatingStatus ) &&
@@ -472,8 +483,40 @@ void CombinedUpdateRenderController::UpdateRenderThread()
     // FRAME TIME
     //////////////////////////////
 
+    extraFramesDropped = 0;
+
+    if (timeToSleepUntil == 0)
+    {
+      // If this is the first frame after the thread is initialized or resumed, we
+      // use the actual time the current frame starts from to calculate the time to
+      // sleep until the next frame.
+      timeToSleepUntil = currentFrameStartTime + mDefaultFrameDurationNanoseconds;
+    }
+    else
+    {
+      // Otherwise, always use the sleep-until time calculated in the last frame to
+      // calculate the time to sleep until the next frame. In this way, if there is
+      // any time gap between the current frame and the next frame, or if update or
+      // rendering in the current frame takes too much time so that the specified
+      // sleep-until time has already passed, it will try to keep the frames syncing
+      // by shortening the duration of the next frame.
+      timeToSleepUntil += mDefaultFrameDurationNanoseconds;
+
+      // Check the current time at the end of the frame
+      uint64_t currentFrameEndTime = 0;
+      TimeService::GetNanoseconds( currentFrameEndTime );
+      while ( currentFrameEndTime > timeToSleepUntil + mDefaultFrameDurationNanoseconds )
+      {
+         // We are more than one frame behind already, so just drop the next frames
+         // until the sleep-until time is later than the current time so that we can
+         // catch up.
+         timeToSleepUntil += mDefaultFrameDurationNanoseconds;
+         extraFramesDropped++;
+      }
+    }
+
     // Sleep until at least the the default frame duration has elapsed. This will return immediately if the specified end-time has already passed.
-    TimeService::SleepUntil( currentFrameStartTime + mDefaultFrameDurationNanoseconds );
+    TimeService::SleepUntil( timeToSleepUntil );
   }
 
   // Inform core of context destruction & shutdown EGL
@@ -486,7 +529,7 @@ void CombinedUpdateRenderController::UpdateRenderThread()
   mEnvironmentOptions.UnInstallLogFunction();
 }
 
-bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bool updateRequired )
+bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bool updateRequired, uint64_t& timeToSleepUntil )
 {
   useElapsedTime = true;
 
@@ -501,6 +544,11 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bo
     LOG_UPDATE_RENDER( "      mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread );
     LOG_UPDATE_RENDER( "      mNewSurface:                 %d", mNewSurface );
 
+    // Reset the time when the thread is waiting, so the sleep-until time for
+    // the first frame after resuming should be based on the actual start time
+    // of the first frame.
+    timeToSleepUntil = 0;
+
     mUpdateRenderThreadWaitCondition.Wait( updateLock );
 
     if( ! mUseElapsedTimeAfterWait )