Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /**
  29.  * @file
  30.  * Cross-platform debugging helpers.
  31.  *
  32.  * For now it just has assert and printf replacements, but it might be extended
  33.  * with stack trace reports and more advanced logging in the near future.
  34.  *
  35.  * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
  36.  */
  37.  
  38. #ifndef U_DEBUG_H_
  39. #define U_DEBUG_H_
  40.  
  41.  
  42. #include "os/os_misc.h"
  43.  
  44. #include "pipe/p_format.h"
  45.  
  46.  
  47. #ifdef  __cplusplus
  48. extern "C" {
  49. #endif
  50.  
  51.  
  52. #if defined(__GNUC__)
  53. #define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
  54. #else
  55. #define _util_printf_format(fmt, list)
  56. #endif
  57.  
  58. void _debug_vprintf(const char *format, va_list ap);
  59.    
  60.  
  61. static INLINE void
  62. _debug_printf(const char *format, ...)
  63. {
  64.    va_list ap;
  65.    va_start(ap, format);
  66.    _debug_vprintf(format, ap);
  67.    va_end(ap);
  68. }
  69.  
  70.  
  71. /**
  72.  * Print debug messages.
  73.  *
  74.  * The actual channel used to output debug message is platform specific. To
  75.  * avoid misformating or truncation, follow these rules of thumb:
  76.  * - output whole lines
  77.  * - avoid outputing large strings (512 bytes is the current maximum length
  78.  * that is guaranteed to be printed in all platforms)
  79.  */
  80. #if !defined(PIPE_OS_HAIKU)
  81. static INLINE void
  82. debug_printf(const char *format, ...) _util_printf_format(1,2);
  83.  
  84. static INLINE void
  85. debug_printf(const char *format, ...)
  86. {
  87. #ifdef DEBUG
  88.    va_list ap;
  89.    va_start(ap, format);
  90.    _debug_vprintf(format, ap);
  91.    va_end(ap);
  92. #else
  93.    (void) format; /* silence warning */
  94. #endif
  95. }
  96. #else /* is Haiku */
  97. /* Haiku provides debug_printf in libroot with OS.h */
  98. #include <OS.h>
  99. #endif
  100.  
  101.  
  102. /*
  103.  * ... isn't portable so we need to pass arguments in parentheses.
  104.  *
  105.  * usage:
  106.  *    debug_printf_once(("answer: %i\n", 42));
  107.  */
  108. #define debug_printf_once(args) \
  109.    do { \
  110.       static boolean once = TRUE; \
  111.       if (once) { \
  112.          once = FALSE; \
  113.          debug_printf args; \
  114.       } \
  115.    } while (0)
  116.  
  117.  
  118. #ifdef DEBUG
  119. #define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
  120. #else
  121. #define debug_vprintf(_format, _ap) ((void)0)
  122. #endif
  123.  
  124.  
  125. #ifdef DEBUG
  126. /**
  127.  * Dump a blob in hex to the same place that debug_printf sends its
  128.  * messages.
  129.  */
  130. void debug_print_blob( const char *name, const void *blob, unsigned size );
  131.  
  132. /* Print a message along with a prettified format string
  133.  */
  134. void debug_print_format(const char *msg, unsigned fmt );
  135. #else
  136. #define debug_print_blob(_name, _blob, _size) ((void)0)
  137. #define debug_print_format(_msg, _fmt) ((void)0)
  138. #endif
  139.  
  140.  
  141. /**
  142.  * Hard-coded breakpoint.
  143.  */
  144. #ifdef DEBUG
  145. #define debug_break() os_break()
  146. #else /* !DEBUG */
  147. #define debug_break() ((void)0)
  148. #endif /* !DEBUG */
  149.  
  150.  
  151. long
  152. debug_get_num_option(const char *name, long dfault);
  153.  
  154. void _debug_assert_fail(const char *expr,
  155.                         const char *file,
  156.                         unsigned line,
  157.                         const char *function);
  158.  
  159.  
  160. /**
  161.  * Assert macro
  162.  *
  163.  * Do not expect that the assert call terminates -- errors must be handled
  164.  * regardless of assert behavior.
  165.  *
  166.  * For non debug builds the assert macro will expand to a no-op, so do not
  167.  * call functions with side effects in the assert expression.
  168.  */
  169. #ifdef DEBUG
  170. #define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
  171. #else
  172. #define debug_assert(expr) do { } while (0 && (expr))
  173. #endif
  174.  
  175.  
  176. /** Override standard assert macro */
  177. #ifdef assert
  178. #undef assert
  179. #endif
  180. #define assert(expr) debug_assert(expr)
  181.  
  182.  
  183. /**
  184.  * Output the current function name.
  185.  */
  186. #ifdef DEBUG
  187. #define debug_checkpoint() \
  188.    _debug_printf("%s\n", __FUNCTION__)
  189. #else
  190. #define debug_checkpoint() \
  191.    ((void)0)
  192. #endif
  193.  
  194.  
  195. /**
  196.  * Output the full source code position.
  197.  */
  198. #ifdef DEBUG
  199. #define debug_checkpoint_full() \
  200.    _debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
  201. #else
  202. #define debug_checkpoint_full() \
  203.    ((void)0)
  204. #endif
  205.  
  206.  
  207. /**
  208.  * Output a warning message. Muted on release version.
  209.  */
  210. #ifdef DEBUG
  211. #define debug_warning(__msg) \
  212.    _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
  213. #else
  214. #define debug_warning(__msg) \
  215.    ((void)0)
  216. #endif
  217.  
  218.  
  219. /**
  220.  * Emit a warning message, but only once.
  221.  */
  222. #ifdef DEBUG
  223. #define debug_warn_once(__msg) \
  224.    do { \
  225.       static bool warned = FALSE; \
  226.       if (!warned) { \
  227.          _debug_printf("%s:%u:%s: one time warning: %s\n", \
  228.                        __FILE__, __LINE__, __FUNCTION__, __msg); \
  229.          warned = TRUE; \
  230.       } \
  231.    } while (0)
  232. #else
  233. #define debug_warn_once(__msg) \
  234.    ((void)0)
  235. #endif
  236.  
  237.  
  238. /**
  239.  * Output an error message. Not muted on release version.
  240.  */
  241. #ifdef DEBUG
  242. #define debug_error(__msg) \
  243.    _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
  244. #else
  245. #define debug_error(__msg) \
  246.    _debug_printf("error: %s\n", __msg)
  247. #endif
  248.  
  249.  
  250. /**
  251.  * Used by debug_dump_enum and debug_dump_flags to describe symbols.
  252.  */
  253. struct debug_named_value
  254. {
  255.    const char *name;
  256.    unsigned long value;
  257.    const char *desc;
  258. };
  259.  
  260.  
  261. /**
  262.  * Some C pre-processor magic to simplify creating named values.
  263.  *
  264.  * Example:
  265.  * @code
  266.  * static const debug_named_value my_names[] = {
  267.  *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
  268.  *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
  269.  *    DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
  270.  *    DEBUG_NAMED_VALUE_END
  271.  * };
  272.  *
  273.  *    ...
  274.  *    debug_printf("%s = %s\n",
  275.  *                 name,
  276.  *                 debug_dump_enum(my_names, my_value));
  277.  *    ...
  278.  * @endcode
  279.  */
  280. #define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL}
  281. #define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
  282. #define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
  283.  
  284.  
  285. /**
  286.  * Convert a enum value to a string.
  287.  */
  288. const char *
  289. debug_dump_enum(const struct debug_named_value *names,
  290.                 unsigned long value);
  291.  
  292. const char *
  293. debug_dump_enum_noprefix(const struct debug_named_value *names,
  294.                          const char *prefix,
  295.                          unsigned long value);
  296.  
  297.  
  298. /**
  299.  * Convert binary flags value to a string.
  300.  */
  301. const char *
  302. debug_dump_flags(const struct debug_named_value *names,
  303.                  unsigned long value);
  304.  
  305.  
  306. /**
  307.  * Function enter exit loggers
  308.  */
  309. #ifdef DEBUG
  310. int debug_funclog_enter(const char* f, const int line, const char* file);
  311. void debug_funclog_exit(const char* f, const int line, const char* file);
  312. void debug_funclog_enter_exit(const char* f, const int line, const char* file);
  313.  
  314. #define DEBUG_FUNCLOG_ENTER() \
  315.    int __debug_decleration_work_around = \
  316.       debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
  317. #define DEBUG_FUNCLOG_EXIT() \
  318.    do { \
  319.       (void)__debug_decleration_work_around; \
  320.       debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
  321.       return; \
  322.    } while(0)
  323. #define DEBUG_FUNCLOG_EXIT_RET(ret) \
  324.    do { \
  325.       (void)__debug_decleration_work_around; \
  326.       debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
  327.       return ret; \
  328.    } while(0)
  329. #define DEBUG_FUNCLOG_ENTER_EXIT() \
  330.    debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
  331.  
  332. #else
  333. #define DEBUG_FUNCLOG_ENTER() \
  334.    int __debug_decleration_work_around
  335. #define DEBUG_FUNCLOG_EXIT() \
  336.    do { (void)__debug_decleration_work_around; return; } while(0)
  337. #define DEBUG_FUNCLOG_EXIT_RET(ret) \
  338.    do { (void)__debug_decleration_work_around; return ret; } while(0)
  339. #define DEBUG_FUNCLOG_ENTER_EXIT()
  340. #endif
  341.  
  342.  
  343. /**
  344.  * Get option.
  345.  *
  346.  * It is an alias for getenv on Linux.
  347.  *
  348.  * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
  349.  * endings with one option per line as
  350.  *  
  351.  *   NAME=value
  352.  *
  353.  * This file must be terminated with an extra empty line.
  354.  */
  355. const char *
  356. debug_get_option(const char *name, const char *dfault);
  357.  
  358. boolean
  359. debug_get_bool_option(const char *name, boolean dfault);
  360.  
  361. long
  362. debug_get_num_option(const char *name, long dfault);
  363.  
  364. unsigned long
  365. debug_get_flags_option(const char *name,
  366.                        const struct debug_named_value *flags,
  367.                        unsigned long dfault);
  368.  
  369. #define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
  370. static boolean \
  371. debug_get_option_ ## sufix (void) \
  372. { \
  373.    static boolean first = TRUE; \
  374.    static boolean value; \
  375.    if (first) { \
  376.       first = FALSE; \
  377.       value = debug_get_bool_option(name, dfault); \
  378.    } \
  379.    return value; \
  380. }
  381.  
  382. #define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
  383. static long \
  384. debug_get_option_ ## sufix (void) \
  385. { \
  386.    static boolean first = TRUE; \
  387.    static long value; \
  388.    if (first) { \
  389.       first = FALSE; \
  390.       value = debug_get_num_option(name, dfault); \
  391.    } \
  392.    return value; \
  393. }
  394.  
  395. #define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
  396. static unsigned long \
  397. debug_get_option_ ## sufix (void) \
  398. { \
  399.    static boolean first = TRUE; \
  400.    static unsigned long value; \
  401.    if (first) { \
  402.       first = FALSE; \
  403.       value = debug_get_flags_option(name, flags, dfault); \
  404.    } \
  405.    return value; \
  406. }
  407.  
  408.  
  409. unsigned long
  410. debug_memory_begin(void);
  411.  
  412. void
  413. debug_memory_end(unsigned long beginning);
  414.  
  415.  
  416. #ifdef DEBUG
  417. struct pipe_context;
  418. struct pipe_surface;
  419. struct pipe_transfer;
  420. struct pipe_resource;
  421.  
  422. void debug_dump_image(const char *prefix,
  423.                       enum pipe_format format, unsigned cpp,
  424.                       unsigned width, unsigned height,
  425.                       unsigned stride,
  426.                       const void *data);
  427. void debug_dump_surface(struct pipe_context *pipe,
  428.                         const char *prefix,
  429.                         struct pipe_surface *surface);  
  430. void debug_dump_texture(struct pipe_context *pipe,
  431.                         const char *prefix,
  432.                         struct pipe_resource *texture);
  433. void debug_dump_surface_bmp(struct pipe_context *pipe,
  434.                             const char *filename,
  435.                             struct pipe_surface *surface);
  436. void debug_dump_transfer_bmp(struct pipe_context *pipe,
  437.                              const char *filename,
  438.                              struct pipe_transfer *transfer, void *ptr);
  439. void debug_dump_float_rgba_bmp(const char *filename,
  440.                                unsigned width, unsigned height,
  441.                                float *rgba, unsigned stride);
  442. #else
  443. #define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
  444. #define debug_dump_surface(pipe, prefix, surface) ((void)0)
  445. #define debug_dump_surface_bmp(pipe, filename, surface) ((void)0)
  446. #define debug_dump_transfer_bmp(filename, transfer, ptr) ((void)0)
  447. #define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0)
  448. #endif
  449.  
  450.  
  451. void
  452. debug_print_transfer_flags(const char *msg, unsigned usage);
  453.  
  454.  
  455. #ifdef  __cplusplus
  456. }
  457. #endif
  458.  
  459. #endif /* U_DEBUG_H_ */
  460.