2 * Copyright (c) 2014 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 "frame-time.h"
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/platform-abstraction.h>
28 using Integration::PlatformAbstraction;
37 #if defined(DEBUG_ENABLED)
38 Integration::Log::Filter* gLogFilter = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_FRAME_TIME");
41 const unsigned int DEFAULT_MINIMUM_FRAME_TIME_INTERVAL( 16667u );
43 const unsigned int MICROSECONDS_PER_SECOND( 1000000u );
44 const unsigned int MICROSECONDS_PER_MILLISECOND( 1000u );
46 const float MICROSECONDS_TO_SECONDS( 0.000001f );
48 const unsigned int HISTORY_SIZE(3);
50 // constants to keep code readability with unsigned int has to be used as boolean (due to multithreading)
51 const unsigned int TRUE = 1u;
52 const unsigned int FALSE = 0u;
53 } // unnamed namespace
56 FrameTime::FrameTime( PlatformAbstraction& platform )
57 : mPlatform( platform ),
58 mMinimumFrameTimeInterval( DEFAULT_MINIMUM_FRAME_TIME_INTERVAL ),
60 mLastSyncTimeAtUpdate( 0u ),
61 mLastSyncFrameNumber( 0u ),
62 mLastUpdateFrameNumber( 0u ),
66 mExtraUpdatesSinceSync( 0u )
69 for ( unsigned int i = 0; i < HISTORY_SIZE; ++i )
71 mPreviousUpdateFrames[i] = 0;
75 mLastSyncTimeAtUpdate = mLastSyncTime;
77 DALI_LOG_INFO( gLogFilter, Debug::Concise, "FrameTime Initialized\n" );
80 FrameTime::~FrameTime()
84 void FrameTime::SetMinimumFrameTimeInterval( unsigned int interval )
86 mMinimumFrameTimeInterval = interval;
89 void FrameTime::SetSyncTime( unsigned int frameNumber )
91 // Only set the render time if we are running
96 mLastSyncFrameNumber = frameNumber;
98 DALI_LOG_INFO( gLogFilter, Debug::General, "FrameTime: SetSyncTime(): Frame: %u: Time: %u\n", mLastSyncFrameNumber, (unsigned int) ( mLastSyncTime / MICROSECONDS_PER_MILLISECOND ) );
102 void FrameTime::Suspend()
107 mLastSyncFrameNumber = 0;
108 mLastUpdateFrameNumber = 0;
110 mExtraUpdatesSinceSync = 0;
113 for ( unsigned int i = 0; i < HISTORY_SIZE; ++i )
115 mPreviousUpdateFrames[i] = 0;
118 DALI_LOG_INFO( gLogFilter, Debug::Concise, "FrameTime: Suspended\n" );
121 void FrameTime::Resume()
123 DALI_LOG_INFO( gLogFilter, Debug::Concise, "FrameTime: Resuming\n" );
125 SetLastSyncTime(); // Should only update the last Sync time so the elapsed time during suspension is taken into consideration when we next update.
131 void FrameTime::Sleep()
133 DALI_LOG_INFO( gLogFilter, Debug::Concise, "FrameTime: Sleeping\n" );
135 // Mimic Suspend behaviour
139 void FrameTime::WakeUp()
141 DALI_LOG_INFO( gLogFilter, Debug::Concise, "FrameTime: Waking Up\n" );
144 mLastSyncTimeAtUpdate = mLastSyncTime; // We do not want any animations to progress as we have just been woken up.
149 void FrameTime::PredictNextSyncTime( float& lastFrameDeltaSeconds, unsigned int& lastSyncTimeMilliseconds, unsigned int& nextSyncTimeMilliseconds )
153 const unsigned int minimumFrameTimeInterval( mMinimumFrameTimeInterval );
154 const uint64_t lastSyncTime( mLastSyncTime );
155 const unsigned int lastSyncFrameNumber( mLastSyncFrameNumber );
157 float lastFrameDelta( 0.0f ); // Assume the last update frame delta is 0.
158 unsigned int framesTillNextSync( 1 ); // Assume next render will be in one Sync frame time.
160 unsigned int framesInLastUpdate( lastSyncFrameNumber - mLastUpdateFrameNumber );
161 lastFrameDelta = lastSyncTime - mLastSyncTimeAtUpdate;
163 // We should only evaluate the previous frame values if this is not the first frame.
166 // Check whether we have had any Syncs since we last did an Update.
167 if ( framesInLastUpdate == 0 )
169 // We have had another update before a Sync, increment counter.
170 ++mExtraUpdatesSinceSync;
172 // This update frame will be rendered mUpdatesSinceSync later.
173 framesTillNextSync += mExtraUpdatesSinceSync;
174 DALI_LOG_INFO(gLogFilter, Debug::Concise, "PredictNextSyncTime UpdateBeforeSync\n");
178 mExtraUpdatesSinceSync = 0;
181 // If more than one frame elapsed since last Update, then check if this is a recurring theme so we can accurately predict when this Update is rendered.
182 if ( framesInLastUpdate > 1 )
184 DALI_LOG_INFO(gLogFilter, Debug::Concise, "PredictNextSyncTime framesInLastUpdate:%u\n", framesInLastUpdate);
185 unsigned int average(0);
186 for ( unsigned int i = 0; i < HISTORY_SIZE; ++i )
188 average += mPreviousUpdateFrames[i];
190 average /= HISTORY_SIZE;
194 // Our average shows a recurring theme, we are missing frames when rendering so calculate number of frames this will take.
195 framesTillNextSync = average;
199 // Write the number of frames the last update took to the array.
200 mPreviousUpdateFrames[writePos] = framesInLastUpdate;
201 writePos = ( writePos + 1 ) % HISTORY_SIZE;
204 mLastUpdateFrameNumber = lastSyncFrameNumber;
205 mLastSyncTimeAtUpdate = lastSyncTime;
208 // Calculate the time till the next render
209 unsigned int timeTillNextRender( minimumFrameTimeInterval * framesTillNextSync );
211 // Set the input variables
212 lastFrameDeltaSeconds = lastFrameDelta * MICROSECONDS_TO_SECONDS;
213 lastSyncTimeMilliseconds = lastSyncTime / MICROSECONDS_PER_MILLISECOND;
214 nextSyncTimeMilliseconds = ( lastSyncTime + timeTillNextRender ) / MICROSECONDS_PER_MILLISECOND;
216 DALI_LOG_INFO( gLogFilter, Debug::General, "FrameTime: Frame: %u, Time: %u, NextTime: %u, LastDelta: %f\n", mLastUpdateFrameNumber, lastSyncTimeMilliseconds, nextSyncTimeMilliseconds, lastFrameDeltaSeconds );
217 DALI_LOG_INFO( gLogFilter, Debug::Verbose, " FramesInLastUpdate: %u, FramesTillNextSync: %u\n", framesInLastUpdate, framesTillNextSync );
221 inline void FrameTime::SetLastSyncTime()
223 unsigned int seconds( 0u );
224 unsigned int microseconds( 0u );
226 mPlatform.GetTimeMicroseconds( seconds, microseconds );
228 mLastSyncTime = seconds; // Promote from 32 bit to 64 bit value
229 mLastSyncTime = ( mLastSyncTime * MICROSECONDS_PER_SECOND ) + microseconds;
232 } // namespace Adaptor
233 } // namespace Internal