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