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