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