MS Windows - Fix compile errors when debug is enabled.
[platform/core/uifw/dali-core.git] / dali / integration-api / debug.cpp
1 /*
2  * Copyright (c) 2018 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 <dali/integration-api/debug.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstdio>
23 #include <cstdarg>
24 #include <cstring>
25 #include <cstdlib>
26 #include <sstream>
27 #include <iomanip>
28 #include <ctime>
29
30 // INTERNAL INCLUDES
31 #include <dali/public-api/common/constants.h>
32 #include <dali/public-api/math/matrix3.h>
33 #include <dali/public-api/math/matrix.h>
34 #include <dali/public-api/math/vector3.h>
35 #include <dali/public-api/math/vector4.h>
36 #include <dali/public-api/math/quaternion.h>
37 #include <dali/internal/event/common/thread-local-storage.h>
38
39 namespace Dali
40 {
41
42 #ifdef DEBUG_ENABLED
43
44 // Fake globals for gdb typedefs
45 Dali::DebugPropertyValueArray gValueArray;
46 Dali::DebugPropertyValueMap   gValueMap;
47
48 #endif
49
50
51 namespace // unnamed namespace
52 {
53
54 const uint64_t NANOSECONDS_PER_SECOND = 1e+9;
55
56 }
57
58 namespace Integration
59 {
60
61 namespace Log
62 {
63
64 thread_local LogFunction gthreadLocalLogFunction = nullptr;
65
66 /* Forward declarations */
67 std::string FormatToString(const char *format, ...);
68 std::string ArgListToString(const char *format, va_list args);
69
70 void LogMessage(DebugPriority priority, const char* format, ...)
71 {
72   if ( !gthreadLocalLogFunction )
73   {
74     return;
75   }
76
77   va_list arg;
78   va_start(arg, format);
79   std::string message = ArgListToString(format, arg);
80   va_end(arg);
81
82   gthreadLocalLogFunction(priority,message);
83 }
84
85 void InstallLogFunction(const LogFunction& logFunction)
86 {
87   // TLS stores a pointer to an object.
88   // It needs to be allocated on the heap, because TLS will destroy it when the thread exits.
89
90   gthreadLocalLogFunction = logFunction;
91 }
92
93 void UninstallLogFunction()
94 {
95   gthreadLocalLogFunction = nullptr;
96 }
97
98 #ifdef DEBUG_ENABLED
99
100 /*Change false to true if trace is needed but don't commit to codeline*/
101 Filter* Filter::gRender     = Filter::New(Debug::Concise, false, "LOG_RENDER");
102 Filter* Filter::gResource   = Filter::New(Debug::Concise, false, "LOG_RESOURCE");
103 Filter* Filter::gGLResource = Filter::New(Debug::Concise, false, "LOG_GL_RESOURCE");
104 Filter* Filter::gObject     = nullptr;
105 Filter* Filter::gImage      = Filter::New(Debug::Concise, false, "LOG_IMAGE");
106 Filter* Filter::gModel      = Filter::New(Debug::Concise, false, "LOG_MODEL");
107 Filter* Filter::gNode       = nullptr;
108 Filter* Filter::gElement    = nullptr;
109 Filter* Filter::gActor      = Filter::New(Debug::Concise, false, "LOG_ACTOR");
110 Filter* Filter::gShader     = Filter::New(Debug::Concise, false, "LOG_SHADER");
111
112 Filter::FilterList* Filter::GetActiveFilters()
113 {
114   static Filter::FilterList* activeFilters = new FilterList;
115   return activeFilters;
116 }
117
118 Filter* Filter::New( LogLevel level, bool trace, const char * environmentVariableName )
119 {
120   char * environmentVariableValue = getenv( environmentVariableName );
121   if ( environmentVariableValue )
122   {
123     unsigned int envLevel(0);
124     char envTraceString(0);
125     sscanf( environmentVariableValue, "%u,%c", &envLevel, &envTraceString );
126
127     if ( envLevel > Verbose )
128     {
129       envLevel = Verbose;
130     }
131     level = LogLevel( envLevel );
132
133     // Just use 'f' and 't' as it's faster than doing full string comparisons
134     if ( envTraceString == 't' )
135     {
136       trace = true;
137     }
138     else if ( envTraceString == 'f' )
139     {
140       trace = false;
141     }
142   }
143
144   Filter* filter = new Filter(level, trace);
145   filter->mNesting++;
146   GetActiveFilters()->push_back(filter);
147   return filter;
148 }
149
150 /**
151  * Enable trace on all filters.
152  */
153 void Filter::EnableGlobalTrace()
154 {
155   for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
156   {
157     (*iter)->EnableTrace();
158   }
159 }
160
161 /**
162  * Disable trace on all filters.
163  */
164 void Filter::DisableGlobalTrace()
165 {
166   for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
167   {
168     (*iter)->DisableTrace();
169   }
170 }
171
172
173 void Filter::Log(LogLevel level, const char* format, ...)
174 {
175   if(level <= mLoggingLevel)
176   {
177     va_list arg;
178     va_start(arg, format);
179
180     if( mTraceEnabled )
181     {
182       char *buffer = nullptr;
183       int numChars = asprintf( &buffer, "    %-*c %s", mNesting, ':', format );
184       if( numChars >= 0 ) // No error
185       {
186         std::string message = ArgListToString( buffer, arg );
187         LogMessage( DebugInfo, message.c_str() );
188         free( buffer );
189       }
190     }
191     else
192     {
193       std::string message = ArgListToString( format, arg );
194       LogMessage( DebugInfo, message.c_str() );
195     }
196     va_end(arg);
197   }
198 }
199
200
201 TraceObj::TraceObj(Filter* filter, const char*format, ...) : mFilter(filter)
202 {
203   if(mFilter && mFilter->IsTraceEnabled())
204   {
205     va_list arg;
206     va_start(arg, format);
207     mMessage = ArgListToString(format, arg);
208     va_end(arg);
209
210     LogMessage(DebugInfo, "Entr%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
211     ++mFilter->mNesting;
212   }
213 }
214
215 TraceObj::~TraceObj()
216 {
217   if(mFilter && mFilter->IsTraceEnabled())
218   {
219     if (mFilter->mNesting)
220     {
221       --mFilter->mNesting;
222     }
223     LogMessage(DebugInfo, "Exit%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
224   }
225 }
226
227 #endif // DEBUG_ENABLED
228
229 std::string ArgListToString(const char *format, va_list args)
230 {
231   std::string str; // empty string
232   if(format != NULL)
233   {
234     char* buffer = NULL;
235     int err = vasprintf(&buffer, format, args);
236     if(err >= 0) // No error
237     {
238       str = buffer;
239       free(buffer);
240     }
241   }
242   return str;
243 }
244
245 std::string FormatToString(const char *format, ...)
246 {
247   va_list arg;
248   va_start(arg, format);
249   std::string s = ArgListToString(format, arg);
250   va_end(arg);
251   return s;
252 }
253
254 void GetNanoseconds( uint64_t& timeInNanoseconds )
255 {
256   timespec timeSpec;
257   clock_gettime( CLOCK_MONOTONIC, &timeSpec );
258
259   // Convert all values to uint64_t to match our return type
260   timeInNanoseconds = ( static_cast< uint64_t >( timeSpec.tv_sec ) * NANOSECONDS_PER_SECOND ) + static_cast< uint64_t >( timeSpec.tv_nsec );
261 }
262
263 } // namespace Log
264
265 } // namespace Integration
266
267 } // namespace Dali