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