[dali_1.2.46] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / integration-api / debug.h
1 #ifndef __DALI_INTEGRATION_DEBUG_H__
2 #define __DALI_INTEGRATION_DEBUG_H__
3
4 /*
5  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <string>
23 #include <sstream>
24 #include <list>
25 #include <stdint.h>
26 #include <dali/public-api/common/vector-wrapper.h>
27 #include <dali/public-api/object/property-map.h>
28
29 // INTERNAL INCLUDES
30 #include <dali/public-api/common/dali-common.h>
31
32 // Using Debug namespace alias shortens the log usage significantly
33 namespace Dali{namespace Integration{namespace Log{}}}
34 namespace Debug = Dali::Integration::Log;
35
36 namespace Dali
37 {
38
39 struct Vector2;
40 struct Vector3;
41 struct Vector4;
42 class Matrix3;
43 class Matrix;
44 class Quaternion;
45
46 #if defined(DEBUG_ENABLED)
47
48 // Less opaque types for debugger
49 typedef std::vector<Dali::Property::Value> DebugPropertyValueArray;
50 typedef std::pair< Property::Index, Property::Value > DebugIndexValuePair;
51 typedef std::vector<Dali::StringValuePair> DebugStringValueContainer;
52 typedef std::vector< DebugIndexValuePair > DebugIndexValueContainer;
53
54 struct DebugPropertyValueMap
55 {
56   DebugStringValueContainer stringValues;
57   DebugIndexValueContainer  intValues;
58 };
59
60 // Fake globals for gdb typedefs
61 extern Dali::DebugPropertyValueArray gValueArray;
62 extern Dali::DebugPropertyValueMap   gValueMap;
63
64 #endif
65
66 namespace Integration
67 {
68 namespace Log
69 {
70
71 enum DebugPriority
72 {
73   DebugInfo,
74   DebugWarning,
75   DebugError
76 };
77
78 /**
79  * Used by logging macros to log a message along with function/class name
80  * @param level debug level
81  * @param format string format
82  */
83 DALI_IMPORT_API void LogMessage(enum DebugPriority level,const char *format, ...);
84
85 /**
86  * typedef for the logging function.
87  */
88 typedef void (*LogFunction)(DebugPriority priority, std::string& message);
89
90 /**
91  * A log function has to be installed for every thread that wants to use logging.
92  * This should be done by the adaptor.
93  * The log function can be different for each thread.
94  * @param logFunction the log function to install
95  * @param logOpts the log options to save in thread
96  */
97 DALI_IMPORT_API void InstallLogFunction(const LogFunction& logFunction);
98
99 /**
100  * A log function has to be uninstalled for every thread that wants to use logging.
101  * The log function can be different for each thread.
102  */
103 DALI_IMPORT_API void UninstallLogFunction();
104
105 /********************************************************************************
106  *                            Error/Warning  macros.                            *
107  ********************************************************************************/
108
109 /**
110  * Provides unfiltered logging for global error level messages
111  */
112 #define DALI_LOG_ERROR(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError,   "%s " format, __PRETTY_FUNCTION__, ## args)
113
114 #define DALI_LOG_ERROR_NOFN(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, format, ## args)
115
116 #define DALI_LOG_WARNING_NOFN(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugWarning, format, ## args)
117
118 /**
119  * Provides unfiltered logging for fps monitor
120  */
121 #define DALI_LOG_FPS(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args)
122
123 /**
124  * Provides unfiltered logging for update status
125  */
126 #define DALI_LOG_UPDATE_STATUS(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args)
127
128 /**
129  * Provides unfiltered logging for render information
130  */
131 #define DALI_LOG_RENDER_INFO(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args)
132
133 #ifdef DEBUG_ENABLED
134
135 /**
136  * Provides unfiltered logging for global warning level messages
137  */
138 #define DALI_LOG_WARNING(format, args...)   Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugWarning, "%s " format, __PRETTY_FUNCTION__, ## args)
139
140
141 #else // DEBUG_ENABLED
142
143 // Don't warn on release build
144 #define DALI_LOG_WARNING(format, args...)
145
146 #endif
147
148 /********************************************************************************
149  *                                    Filter                                    *
150  ********************************************************************************/
151
152 #ifdef DEBUG_ENABLED
153
154 /**
155  * Enumeration of logging levels.
156  * Used by the filters to provide multiple log levels.
157  * In general, the higher the value, the more debug is available for that filter.
158  */
159 enum LogLevel
160 {
161   NoLogging   = 0,
162   Concise     = 1,
163   General     = 2,
164   Verbose     = 3
165 };
166
167
168 /**
169  * The Filter object is used by the DALI_LOG_INFO macro and others to determine if the logging
170  * should take place, and routes the logging via the platform abstraction's LogMessage.
171  *
172  * It provides a logging level. If this is set to zero, then DALI_LOG_INFO won't log anything.
173  * It provides the ability to turn tracing on or off.
174  *
175  */
176 class DALI_IMPORT_API Filter
177 {
178 public:
179   typedef std::list<Filter*>           FilterList;
180   typedef std::list<Filter*>::iterator FilterIter;
181
182 public:
183
184   /**
185    * Test if the filter is enabled for the given logging level
186    * @param[in] level - the level to test.
187    * @return true if this level of logging is enabled.
188    */
189   bool IsEnabledFor(LogLevel level) { return level != Debug::NoLogging && level <= mLoggingLevel;}
190
191   /**
192    * Test if trace is enabled for this filter.
193    * @return true if trace is enabled;
194    */
195   bool IsTraceEnabled() { return mTraceEnabled; }
196
197   /**
198    * Enable tracing on this filter.
199    */
200   void EnableTrace() { mTraceEnabled = true; }
201
202   /**
203    * Disable tracing on this filter.
204    */
205   void DisableTrace() { mTraceEnabled = false; }
206
207   /**
208    * Set the log level for this filter. Setting to a higher value than Debug::General also
209    * enables General;
210    */
211   void SetLogLevel(LogLevel level) { mLoggingLevel = level; }
212
213   /**
214    * Perform the logging for this filter.
215    */
216   void Log(LogLevel level, const char* format, ...);
217
218   /**
219    * Create a new filter whose debug level and trace can be modified through the use of an
220    * environment variable.
221    *
222    * @param[in] level The default log level
223    * @param[in] trace The default trace level. If true, function tracing is on.
224    * @param[in] environmentVariableName The environment variable name used in order to change the
225    *                                    log level or trace.
226    *
227    * @info To modify logg level/trace at runtime, you can should define your filter as shown below:
228    *
229    * @code
230    * Debug::Filter* filter = Debug::Filter::New( Debug::NoLogging, false, "FILTER_ENV" );
231    * @endcode
232    *
233    * And to use it when running an executable:
234    * @code
235    * FILTER_ENV=3 dali-demo        // LogLevel Verbose,   Trace using default
236    * FILTER_ENV=1,true dali-demo   // LogLevel Concise,   Trace ON
237    * FILTER_ENV=2,false dali-demo  // LogLevel General,   Trace OFF
238    * FILTER_ENV=0,true dali-demo   // LogLevel NoLogging, Trace ON
239    * @endcode
240    */
241   static Filter* New(LogLevel level, bool trace, const char * environmentVariableName );
242
243   /**
244    * Enable trace on all filters.
245    */
246   void EnableGlobalTrace();
247
248   /**
249    * Disable trace on all filters.
250    */
251   void DisableGlobalTrace();
252
253 private:
254
255   /**
256    * Constructor.
257    * @param[in] level - the highest log level.
258    * @param[in] trace - whether this filter allows tracing.
259    */
260   Filter(LogLevel level, bool trace) : mLoggingLevel(level), mTraceEnabled(trace), mNesting(0) {}
261
262   static FilterList* GetActiveFilters();
263
264 public:
265   // High level filters. If these filters are too broad for your current requirement, then
266   // you can add a filter to your own class or source file. If you do, use Filter::New()
267   // to tell this class about it.
268
269   static Filter *gRender;
270   static Filter *gResource;
271   static Filter *gGLResource;
272   static Filter *gObject;
273   static Filter *gImage;
274   static Filter *gModel;
275   static Filter *gNode;
276   static Filter *gElement;
277   static Filter *gActor;
278   static Filter *gShader;
279
280 private:
281   LogLevel mLoggingLevel;
282   bool     mTraceEnabled;
283 public:
284   int      mNesting;
285
286 };
287
288
289 #define  DALI_LOG_FILTER_SET_LEVEL(filter, level) filter->SetLogLevel(level)
290 #define  DALI_LOG_FILTER_ENABLE_TRACE(filter)     filter->EnableTrace()
291 #define  DALI_LOG_FILTER_DISABLE_TRACE(filter)    filter->DisableTrace()
292
293 #else
294
295 #define  DALI_LOG_FILTER_SET_LEVEL(filter, level)
296 #define  DALI_LOG_FILTER_ENABLE_TRACE(filter)
297 #define  DALI_LOG_FILTER_DISABLE_TRACE(filter)
298
299 #endif
300
301 /********************************************************************************
302  *                            General Logging macros                            *
303  ********************************************************************************/
304
305 #ifdef DEBUG_ENABLED
306
307 #define DALI_LOG_INFO(filter, level, format, args...)                        \
308   if(filter && filter->IsEnabledFor(level)) { filter->Log(level, format,  ## args); }
309
310 #else // DEBUG_ENABLED
311
312 #define DALI_LOG_INFO(filter, level, format, args...)
313
314 #endif // DEBUG_ENABLED
315
316
317 /********************************************************************************
318  *                                  Trace Macros                                *
319  ********************************************************************************/
320
321 /*
322  * These macros allow the instrumentation of methods. These translate into calls
323  * to LogMessage(DebugInfo).
324  */
325
326 #ifdef DEBUG_ENABLED
327
328 class DALI_IMPORT_API TraceObj
329 {
330 public:
331   TraceObj(Filter* filter, const char* fmt, ...);
332   ~TraceObj();
333
334 public:
335   std::string mMessage;
336   Filter* mFilter;
337 };
338
339
340 #define DALI_LOG_TRACE_METHOD_FMT(filter, format, args...)                 \
341   Dali::Integration::Log::TraceObj debugTraceObj(filter, "%s: " format, __PRETTY_FUNCTION__, ## args)
342
343 #define DALI_LOG_TRACE_METHOD(filter)                                      \
344   Dali::Integration::Log::TraceObj debugTraceObj(filter, __PRETTY_FUNCTION__)
345
346
347 #else // DEBUG_ENABLED
348
349 #define DALI_LOG_TRACE_METHOD_FMT(filter, format, args...)
350 #define DALI_LOG_TRACE_METHOD(filter)
351
352
353 #endif
354
355 /********************************************************************************
356  *                              Extra object debug                              *
357  ********************************************************************************/
358
359 #ifdef DEBUG_ENABLED
360
361 /**
362  * Warning, this macro changes the current scope, so should usually be put at the
363  * end of the class definition.
364  *
365  * Suggest that the value is usually set to the object's name.
366  * Warning - this will increase the size of the object for a debug build.
367  */
368 #define DALI_LOG_OBJECT_STRING_DECLARATION \
369 public: \
370   std::string mDebugString;
371
372 /**
373  * Print all the actor tree names
374  **/
375 #define DALI_LOG_ACTOR_TREE( node ) { \
376   std::stringstream branch; \
377   Node* tempNode = node; \
378   while( tempNode ) { \
379     branch << "<" << tempNode->mDebugString << ">::"; \
380     tempNode = tempNode->GetParent(); \
381   } \
382   DALI_LOG_ERROR_NOFN("Actor tree: %s\n", branch.str().c_str()); \
383 }
384
385 /**
386  * Allows one object to set another object's debug string
387  */
388 #define DALI_LOG_SET_OBJECT_STRING(object, string) (object->mDebugString = string)
389
390 /**
391  * Allows one object to set another object's std::string easily
392  */
393 #define DALI_LOG_FMT_OBJECT_STRING(object, fmt, args...) (object->mDebugString = FormatToString(fmt, ## args))
394
395 /**
396  * Allows one object to get another object's debug string
397  */
398 #define DALI_LOG_GET_OBJECT_STRING(object) (object->mDebugString)
399
400 /**
401  * Get the C string (for use in formatted logging)
402  */
403 #define DALI_LOG_GET_OBJECT_C_STR(object) (object->mDebugString.c_str())
404
405 /**
406  * Filtered logging of the object's debug string
407  */
408 #define DALI_LOG_OBJECT(filter, object)  DALI_LOG_INFO(filter, Debug::General, object->mDebugString)
409
410
411 #else // DEBUG_ENABLED
412
413 #define DALI_LOG_OBJECT_STRING_DECLARATION
414 #define DALI_LOG_ACTOR_TREE(node)
415 #define DALI_LOG_SET_OBJECT_STRING(object, string)
416 #define DALI_LOG_FMT_OBJECT_STRING(object, fmt, args...)
417 #define DALI_LOG_GET_OBJECT_STRING(object)
418 #define DALI_LOG_GET_OBJECT_C_STR(object) ""
419 #define DALI_LOG_OBJECT(filter, object)
420
421 #endif
422
423 /********************************************************************************
424  *                                Helper writers                                *
425  ********************************************************************************/
426
427 /**
428  * Helper method to translate a color to a string.
429  * @param[in] color - the color to translate
430  * @return string - the text representation of the color.
431  */
432 DALI_IMPORT_API std::string ColorToString(const Vector4& color);
433
434 /**
435  * Helper method to translate a vector4 to a string.
436  * @param[in] v - the vector
437  * @param[in] precision - the precision to write the float data.
438  * @param[in] indent - the indent level to use.
439  * @return string - the text representation of the vector.
440  */
441 DALI_IMPORT_API std::string Vector4ToString(const Vector4& v, size_t precision=3, size_t indent=0);
442
443 /**
444  * Helper method to translate a vector4 to a string.
445  * @param[in] v - the vector
446  * @param[in] precision - the precision to write the float data.
447  * @param[in] indent - the indent level to use.
448  * @return string - the text representation of the vector.
449  */
450 DALI_IMPORT_API std::string Vector3ToString(const Vector3& v, size_t precision=3, size_t indent=0);
451
452 /**
453  * Helper method to translate a quaternion to a string.
454  * @param[in] q the quaternion
455  * @param[in] precision - the precision to write the float data.
456  * @param[in] indent - the indent level to use.
457  * @return string - the text representation of the quaternion.
458  */
459 DALI_IMPORT_API std::string QuaternionToString(const Quaternion& q, size_t precision=3, size_t indent=0);
460
461 /**
462  * Helper method to translate a 3x3 matrix to a string.
463  * @param[in] m - the matrix
464  * @param[in] precision - the precision to write the float data.
465  * @param[in] indent - the indent level to use.
466  * @return string - the text representation of the vector.
467  */
468 DALI_IMPORT_API std::string Matrix3ToString(const Matrix3& m, size_t precision=3, size_t indent=0);
469
470 /**
471  * Helper method to translate a 4x4 matrix to a string.
472  * @param[in] m - the matrix
473  * @param[in] precision - the precision to write the float data.
474  * @param[in] indent - the indent level to use.
475  * @return string - the text representation of the vector.
476  */
477 DALI_IMPORT_API std::string MatrixToString(const Matrix& m, size_t precision=3, size_t indent=0);
478
479 #ifdef DEBUG_ENABLED
480
481
482 /**
483  * Filtered write of a matrix
484  */
485 #define DALI_LOG_MATRIX(filter, matrix)  DALI_LOG_INFO(filter, Debug::General, MatrixToString(matrix))
486
487 /**
488  * Filtered write of a vector
489  */
490 #define DALI_LOG_VECTOR4(filter, vector) DALI_LOG_INFO(filter, Debug::General, Vector4ToString(vector))
491
492 /**
493  * Filtered write of a vector
494  */
495 #define DALI_LOG_VECTOR3(filter, vector) DALI_LOG_INFO(filter, Debug::General, Vector3ToString(vector))
496
497 /**
498  * Filtered write of a color
499  */
500 #define DALI_LOG_COLOR(filter, color)    DALI_LOG_INFO(filter, Debug::General, ColorToString(color))
501
502 #else
503
504 #define DALI_LOG_MATRIX(filter, matrix)
505 #define DALI_LOG_VECTOR4(filter,vector)
506 #define DALI_LOG_VECTOR3(filter,vector)
507 #define DALI_LOG_COLOR(filter, color)
508
509 #endif
510
511 /********************************************************************************
512  *                            Time instrumentation                              *
513  ********************************************************************************/
514
515 #if defined(DEBUG_ENABLED)
516
517 void GetNanoseconds( uint64_t& timeInNanoseconds );
518
519 #define DALI_LOG_TIMER_START( timeVariable )      \
520   uint64_t timeVariable##1; \
521   Debug::GetNanoseconds( timeVariable##1 );
522
523 #define DALI_LOG_TIMER_END( timeVariable, filter, level, preString)  \
524   uint64_t timeVariable##2; \
525   Debug::GetNanoseconds( timeVariable##2 );                             \
526   DALI_LOG_INFO( filter, level, preString " %ld uSec\n", ((timeVariable##2-timeVariable##1)/1000));
527
528 #else // DEBUG_ENABLED
529
530 #define DALI_LOG_TIMER_START( timeVariable )
531 #define DALI_LOG_TIMER_END( timeVariable, filter, level, preString)
532
533 #endif
534
535 } // Debug
536 } // Integration
537 } // Dali
538
539
540 #endif // __DALI_INTEGRATION_DEBUG_H__