Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-core.git] / dali / integration-api / debug.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/integration-api/debug.h>
19
20 // EXTERNAL INCLUDES
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <sstream>
25 #include <iomanip>
26
27 #ifndef EMSCRIPTEN
28 # include <boost/thread/tss.hpp>
29 #endif
30
31 // INTERNAL INCLUDES
32 #include <dali/public-api/common/constants.h>
33 #include <dali/public-api/math/matrix3.h>
34 #include <dali/public-api/math/matrix.h>
35 #include <dali/public-api/math/vector3.h>
36 #include <dali/public-api/math/vector4.h>
37 #include <dali/public-api/math/quaternion.h>
38 #include <dali/internal/event/common/thread-local-storage.h>
39
40 namespace Dali
41 {
42
43 namespace // unnamed namespace
44 {
45
46 /**
47  * Generic function to print out any 2-Dimensional array
48  * @param[in] data pointer to the source data stored as float[rows][cols]
49  * @param[in] rows number of rows in 2D array
50  * @param[in] cols number of columns in 2D array
51  * @param[in] precision - the precision to write the float data.
52  * @param[in] indent - the indent level to use.
53  * @return string - the text representation of the 2D array
54  */
55 std::string Array2DToString(const float *data, unsigned int rows, unsigned int cols, size_t precision, size_t indent)
56 {
57   std::ostringstream oss;
58
59   std::ios_base::fmtflags mask = oss.flags();
60   mask &= ~std::ios_base::scientific;
61   mask |=  std::ios_base::fixed;
62
63   for(unsigned int rowIdx = 0; rowIdx < rows; rowIdx++)
64   {
65     oss  << std::setw(indent) << std::setfill(' ') << ' ' << "[ ";
66     oss  << std::setfill(' ') << std::setprecision(precision) << std::right << std::setiosflags(mask);
67
68     for(unsigned int colIdx = 0; colIdx < cols; colIdx++)
69     {
70       oss << std::setw(precision + 6) << (*data++) << ' ';
71     }
72
73     oss << ']' << std::endl;
74   }
75
76   return oss.str();
77 }
78
79 }
80
81 namespace Integration
82 {
83
84 namespace Log
85 {
86
87 typedef LogFunction* LogFunctionPtr; ///< LogFunction pointer
88
89 /**
90  * This stores a pointer to a log function in thread local storage.
91  * The data has to be allocated from the heap because
92  * it will automatically be deleted when the thread terminates
93  */
94 struct ThreadLocalLogging
95 {
96   ThreadLocalLogging(LogFunction func)
97   :function(func)
98   {
99   }
100
101   LogFunction function;
102 };
103
104 #ifndef EMSCRIPTEN // single threaded
105 boost::thread_specific_ptr<ThreadLocalLogging> threadLocal;
106 #else
107 std::auto_ptr<ThreadLocalLogging> threadLocal;
108 #endif
109
110 /* Forward declarations */
111 std::string FormatToString(const char *format, ...);
112 std::string ArgListToString(const char *format, va_list args);
113
114 void LogMessage(DebugPriority priority, const char* format, ...)
115 {
116   ThreadLocalLogging* threadLogging = threadLocal.get();
117   // see if there is a log function for this thread
118   if (!threadLogging)
119   {
120     return;
121   }
122   const LogFunction& logfunction = threadLogging->function;
123   if (!logfunction)
124   {
125     return;
126   }
127
128   va_list arg;
129   va_start(arg, format);
130   std::string message = ArgListToString(format, arg);
131   va_end(arg);
132
133   logfunction(priority,message);
134 }
135
136 void InstallLogFunction(const LogFunction& logFunction)
137 {
138   // TLS stores a pointer to an object.
139   // It needs to be allocated on the heap, because TLS will destroy it when the thread exits.
140
141   ThreadLocalLogging* logStruct = new ThreadLocalLogging(logFunction);
142
143   threadLocal.reset(logStruct);
144 }
145
146 void UninstallLogFunction()
147 {
148   threadLocal.reset();
149 }
150
151 #ifdef DEBUG_ENABLED
152
153 /*Change false to true if trace is needed but don't commit to codeline*/
154 Filter* Filter::gRender     = Filter::New(Debug::Concise, false, "LOG_RENDER");
155 Filter* Filter::gResource   = Filter::New(Debug::Concise, false, "LOG_RESOURCE");
156 Filter* Filter::gGLResource = Filter::New(Debug::Concise, false, "LOG_GL_RESOURCE");
157 Filter* Filter::gObject     = NULL;
158 Filter* Filter::gImage      = Filter::New(Debug::Concise, false, "LOG_IMAGE");
159 Filter* Filter::gModel      = Filter::New(Debug::Concise, false, "LOG_MODEL");
160 Filter* Filter::gNode       = NULL;
161 Filter* Filter::gElement    = NULL;
162 Filter* Filter::gActor      = Filter::New(Debug::Concise, false, "LOG_ACTOR");
163 Filter* Filter::gShader     = Filter::New(Debug::Concise, false, "LOG_SHADER");
164 Filter* Filter::gDynamics   = Filter::New(Debug::Concise, false, "LOG_DYNAMICS");
165
166 Filter::FilterList* Filter::GetActiveFilters()
167 {
168   static Filter::FilterList* activeFilters = new FilterList;
169   return activeFilters;
170 }
171
172 Filter* Filter::New( LogLevel level, bool trace, const char * environmentVariableName )
173 {
174   char * environmentVariableValue = getenv( environmentVariableName );
175   if ( environmentVariableValue )
176   {
177     unsigned int envLevel(0);
178     char envTraceString(0);
179     sscanf( environmentVariableValue, "%u,%c", &envLevel, &envTraceString );
180
181     if ( envLevel > Verbose )
182     {
183       envLevel = Verbose;
184     }
185     level = LogLevel( envLevel );
186
187     // Just use 'f' and 't' as it's faster than doing full string comparisons
188     if ( envTraceString == 't' )
189     {
190       trace = true;
191     }
192     else if ( envTraceString == 'f' )
193     {
194       trace = false;
195     }
196   }
197
198   Filter* filter = new Filter(level, trace);
199   filter->mNesting++;
200   GetActiveFilters()->push_back(filter);
201   return filter;
202 }
203
204 /**
205  * Enable trace on all filters.
206  */
207 void Filter::EnableGlobalTrace()
208 {
209   for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
210   {
211     (*iter)->EnableTrace();
212   }
213 }
214
215 /**
216  * Disable trace on all filters.
217  */
218 void Filter::DisableGlobalTrace()
219 {
220   for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
221   {
222     (*iter)->DisableTrace();
223   }
224 }
225
226
227 void Filter::Log(LogLevel level, const char* format, ...)
228 {
229   if(level <= mLoggingLevel)
230   {
231     va_list arg;
232     va_start(arg, format);
233
234     char *buffer = NULL;
235     int numChars = asprintf(&buffer, "%-*c %s", mNesting, ':', format);
236     if(numChars >= 0) // No error
237     {
238       std::string message = ArgListToString(buffer, arg);
239       LogMessage(DebugInfo, message.c_str());
240       free(buffer);
241     }
242     va_end(arg);
243   }
244 }
245
246
247 TraceObj::TraceObj(Filter* filter, const char*format, ...) : mFilter(filter)
248 {
249   if(mFilter && mFilter->IsTraceEnabled())
250   {
251     va_list arg;
252     va_start(arg, format);
253     mMessage = ArgListToString(format, arg);
254     va_end(arg);
255
256     LogMessage(DebugInfo, "Entr%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
257     ++mFilter->mNesting;
258   }
259 }
260
261 TraceObj::~TraceObj()
262 {
263   if(mFilter && mFilter->IsTraceEnabled())
264   {
265     if (mFilter->mNesting)
266     {
267       --mFilter->mNesting;
268     }
269     LogMessage(DebugInfo, "Exit%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
270   }
271 }
272
273 #endif // DEBUG_ENABLED
274
275
276 std::string ArgListToString(const char *format, va_list args)
277 {
278   std::string str; // empty string
279   if(format != NULL)
280   {
281     char* buffer = NULL;
282     int err = vasprintf(&buffer, format, args);
283     if(err >= 0) // No error
284     {
285       str = buffer;
286       free(buffer);
287     }
288   }
289   return str;
290 }
291
292 std::string FormatToString(const char *format, ...)
293 {
294   va_list arg;
295   va_start(arg, format);
296   std::string s = ArgListToString(format, arg);
297   va_end(arg);
298   return s;
299 }
300
301 std::string ColorToString(const Vector4& color)
302 {
303   std::ostringstream oss;
304   oss << "<R:" << color.r << " G:" << color.g << " B:" << color.b << " A:" << color.a << ">";
305   return oss.str();
306 }
307
308 std::string Vector4ToString(const Vector4& v, size_t precision, size_t indent)
309 {
310   std::ostringstream oss;
311   oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right;
312   oss << "<X:" << std::setw(precision+4) << v.x
313       << " Y:" << std::setw(precision+4) << v.y
314       << " Z:" << std::setw(precision+4) << v.z
315       << " W:" << std::setw(precision+4) << v.w << ">";
316   return oss.str();
317 }
318
319 std::string Vector3ToString(const Vector3& v, size_t precision, size_t indent)
320 {
321   std::ostringstream oss;
322   oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right << std::setiosflags(std::ios_base::fixed);
323   oss << "<X:" << std::setw(precision+4) << v.x
324       << " Y:" << std::setw(precision+4) << v.y
325       << " Z:" << std::setw(precision+4) << v.z << ">";
326   return oss.str();
327 }
328
329 std::string QuaternionToString(const Quaternion& q, size_t precision, size_t indent)
330 {
331   std::ostringstream oss;
332
333   Vector3 axis;
334   float angle;
335   q.ToAxisAngle(axis, angle);
336
337   oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right;
338   oss << "<A:" << std::setw(precision+4) << angle * 180.0 / Math::PI << ", " << Vector3ToString(axis, precision, 0) << ">";
339
340   return oss.str();
341 }
342
343 std::string Matrix3ToString(const Matrix3& m, size_t precision, size_t indent)
344 {
345   return Array2DToString(m.AsFloat(), 3, 3, precision, indent);
346 }
347
348 std::string MatrixToString(const Matrix& m, size_t precision, size_t indent)
349 {
350   return Array2DToString(m.AsFloat(), 4, 4, precision, indent);
351 }
352
353 } // namespace Log
354
355 } // namespace Integration
356
357 } // namespace Dali