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