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