Merge "Redesigning render sync to handle reduced frequency" into tizen
[platform/core/uifw/dali-adaptor.git] / adaptors / base / performance-logging / performance-server.cpp
1 /*
2  * Copyright (c) 2014 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
19 #include "performance-server.h"
20
21 // INTERNAL INCLUDES
22 #include <base/environment-options.h>
23 #include <dali/integration-api/platform-abstraction.h>
24
25 namespace Dali
26 {
27
28 namespace Internal
29 {
30
31 namespace Adaptor
32 {
33
34 #define TIME_FMT "%0.2f ms" // 2 decimal places, e.g. 5.34 ms
35 #define TOTAL_TIME_FMT "%0.1f secs" // 1 decimal place, e.g. 4.5 seconds
36
37
38 namespace
39 {
40 const unsigned int DEFAULT_LOG_FREQUENCEY = 2;        ///< default log frequency = 2
41 const unsigned int MILLISECONDS_PER_SECOND = 1000;    ///< 1000 milliseconds per second
42 const unsigned int MICROSECONDS_PER_SECOND = 1000000; ///< 1000000 microseconds per second
43 }
44
45
46 PerformanceServer::PerformanceServer( AdaptorInternalServices& adaptorServices,
47                                       const EnvironmentOptions& environmentOptions)
48 :mLoggingEnabled( false),
49  mLogFunctionInstalled( false ),
50  mLogFrequencyMicroseconds( 0),
51  mPlatformAbstraction( adaptorServices.GetPlatformAbstractionInterface() ),
52  mEnvironmentOptions(environmentOptions),
53  mKernelTrace( adaptorServices.GetKernelTraceInterface() )
54 {
55   SetLogging( mEnvironmentOptions.GetPerformanceLoggingLevel(), mEnvironmentOptions.GetFrameRateLoggingFrequency());
56 }
57
58 PerformanceServer::~PerformanceServer()
59 {
60   if( mLogFunctionInstalled )
61   {
62     mEnvironmentOptions.UnInstallLogFunction();
63   }
64 }
65 void PerformanceServer::SetLogging( unsigned int level, unsigned int interval)
66 {
67   if( level == 0)
68   {
69     mLoggingEnabled = false;
70     return;
71   }
72   mLogLevel = level;
73
74   mLogFrequencyMicroseconds = interval * MICROSECONDS_PER_SECOND;
75
76   if( mLogFrequencyMicroseconds == 0 )
77   {
78     mLogFrequencyMicroseconds = DEFAULT_LOG_FREQUENCEY * MICROSECONDS_PER_SECOND;
79   }
80   mLoggingEnabled = true;
81
82 }
83
84 void PerformanceServer::AddMarker( PerformanceMarker::MarkerType markerType )
85 {
86   if( !mLoggingEnabled )
87   {
88     return;
89   }
90
91   unsigned int seconds(0);
92   unsigned int microseconds(0);
93
94   // get the time
95   mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
96
97   // create a marker
98   PerformanceMarker marker( markerType, FrameTimeStamp( 0, seconds, microseconds ));
99
100   AddMarkerToLog( marker );
101 }
102
103 void PerformanceServer::AddMarkerToLog( PerformanceMarker marker )
104 {
105   // Add Marker can be called from any thread
106   boost::mutex::scoped_lock sharedDatalock( mDataMutex );
107
108   // store the marker
109   mMarkers.PushBack( marker );
110
111   if( mLogLevel & LOG_EVENTS_TO_KERNEL )
112   {
113     mKernelTrace.Trace(marker.GetName());
114   }
115
116   // only log on the v-sync thread, so we have less impact on update/render
117   if( marker.GetType() != PerformanceMarker::V_SYNC )
118   {
119     return;
120   }
121
122   // log out every mLogFrequency.
123   // check difference between first and last frame
124   unsigned int microseconds = PerformanceMarker::MicrosecondDiff( mMarkers[0], marker );
125
126   if( microseconds  >=  mLogFrequencyMicroseconds )
127   {
128     LogMarkers( );
129     mMarkers.Clear();
130
131     // reset data for update / render statistics
132     mUpdateStats.Reset();
133     mRenderStats.Reset();
134     mEventStats.Reset();
135   }
136 }
137
138 void PerformanceServer::LogMarker(const char* name, const FrameTimeStats& frameStats)
139 {
140   // make sure log function is installed, note this will be called only from v-sync thread
141   // if the v-sync thread has already installed one, it won't make any difference.
142   if(! mLogFunctionInstalled )
143   {
144     mEnvironmentOptions.InstallLogFunction();
145     mLogFunctionInstalled = true;
146   }
147
148   // this will always log regardless of debug / release mode
149   Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo,
150                                     "%s , min " TIME_FMT ", max " TIME_FMT ", total (" TOTAL_TIME_FMT "), avg " TIME_FMT "\n",
151                                      name,
152                                      frameStats.GetMinTime() * MILLISECONDS_PER_SECOND,
153                                      frameStats.GetMaxTime() * MILLISECONDS_PER_SECOND,
154                                      frameStats.GetTotalTime(),
155                                      frameStats.GetRollingAverageTime() * MILLISECONDS_PER_SECOND);
156 }
157
158 void PerformanceServer::LogMarkers()
159 {
160   // insert time stamps into a frame-time-stats object, based on type
161   for( MarkerVector::SizeType i = 0; i < mMarkers.Size(); ++i)
162   {
163     const PerformanceMarker& marker = mMarkers[i];
164     switch( marker.GetType() )
165     {
166       case PerformanceMarker::UPDATE_START:
167       {
168         mUpdateStats.StartTime( marker.GetTimeStamp() );
169         break;
170       }
171       case PerformanceMarker::UPDATE_END:
172       {
173         mUpdateStats.EndTime( marker.GetTimeStamp() );
174         break;
175       }
176       case PerformanceMarker::RENDER_START:
177       {
178         mRenderStats.StartTime( marker.GetTimeStamp() );
179         break;
180       }
181       case PerformanceMarker::RENDER_END:
182       {
183         mRenderStats.EndTime( marker.GetTimeStamp() );
184         break;
185       }
186       case PerformanceMarker::PROCESS_EVENTS_START:
187       {
188         mEventStats.StartTime( marker.GetTimeStamp() );
189         break;
190       }
191       case PerformanceMarker::PROCESS_EVENTS_END:
192       {
193         mEventStats.EndTime( marker.GetTimeStamp() );
194         break;
195       }
196       default:
197       {
198         break;
199       }
200     }
201   }
202   if( mLogLevel & LOG_UPDATE_RENDER )
203   {
204     LogMarker("Update",mUpdateStats);
205     LogMarker("Render",mRenderStats);
206   }
207   if( mLogLevel & LOG_EVENT_PROCESS )
208   {
209     LogMarker("Event",mEventStats);
210   }
211
212 }
213
214 } // namespace Internal
215
216 } // namespace Adaptor
217
218 } // namespace Dali