1/*
2 * Copyright © 2009 Pauli Nieminen
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * The above copyright notice and this permission notice (including the
22 * next paragraph) shall be included in all copies or substantial portions
23 * of the Software.
24 */
25/*
26 * Authors:
27 *      Pauli Nieminen <suokkos@gmail.com>
28 */
29
30#ifndef RADEON_DEBUG_H_INCLUDED
31#define RADEON_DEBUG_H_INCLUDED
32
33#include <stdlib.h>
34
35typedef enum radeon_debug_levels {
36	RADEON_CRITICAL  = 0, /* Only errors */
37	RADEON_IMPORTANT = 1, /* Important warnings and messages */
38	RADEON_NORMAL    = 2, /* Normal log messages usefull for debugging */
39	RADEON_VERBOSE   = 3, /* Extra details to debugging */
40	RADEON_TRACE     = 4  /* Log about everything that happens */
41} radeon_debug_level_t;
42
43/**
44 * Compile time option to change level of debugging compiled to dri driver.
45 * Selecting critical level is not recommended because perfromance gains are
46 * going to minimal but you will lose a lot of important warnings in case of
47 * errors.
48 */
49#ifndef RADEON_DEBUG_LEVEL
50# ifdef DEBUG
51#  define RADEON_DEBUG_LEVEL RADEON_TRACE
52# else
53#  define RADEON_DEBUG_LEVEL RADEON_VERBOSE
54# endif
55#endif
56
57typedef enum radeon_debug_types {
58	RADEON_TEXTURE   = 0x00001,
59	RADEON_STATE     = 0x00002,
60	RADEON_IOCTL     = 0x00004,
61	RADEON_RENDER    = 0x00008,
62	RADEON_SWRENDER  = 0x00010,
63	RADEON_FALLBACKS = 0x00020,
64	RADEON_VFMT      = 0x00040,
65	RADEON_SHADER    = 0x00080,
66	RADEON_CS        = 0x00100,
67	RADEON_DRI       = 0x00200,
68	RADEON_DMA       = 0x00400,
69	RADEON_SANITY    = 0x00800,
70	RADEON_SYNC      = 0x01000,
71	RADEON_PIXEL     = 0x02000,
72	RADEON_MEMORY    = 0x04000,
73	RADEON_VERTS     = 0x08000,
74	RADEON_GENERAL   = 0x10000   /* Used for errors and warnings */
75} radeon_debug_type_t;
76
77#define RADEON_MAX_INDENT 5
78
79struct radeon_debug {
80       size_t indent_depth;
81       char indent[RADEON_MAX_INDENT];
82};
83
84extern radeon_debug_type_t radeon_enabled_debug_types;
85
86/**
87 * Compabibility layer for old debug code
88 **/
89#define RADEON_DEBUG radeon_enabled_debug_types
90
91static inline int radeon_is_debug_enabled(const radeon_debug_type_t type,
92	   const radeon_debug_level_t level)
93{
94       return RADEON_DEBUG_LEVEL >= level
95		&& (type & radeon_enabled_debug_types);
96}
97/*
98 * define macro for gcc specific __attribute__ if using alternative compiler
99 */
100#ifndef __GNUC__
101#define  __attribute__(x)  /*empty*/
102#endif
103
104
105extern void _radeon_print(const radeon_debug_type_t type,
106	   const radeon_debug_level_t level,
107	   const char* message,
108	   ...)  __attribute__((format(printf,3,4)));
109/**
110 * Print out debug message if channel specified by type is enabled
111 * and compile time debugging level is at least as high as level parameter
112 */
113#define radeon_print(type, level, ...) do {			\
114	const radeon_debug_level_t _debug_level = (level);	\
115	const radeon_debug_type_t _debug_type = (type);		\
116	/* Compile out if level of message is too high */	\
117	if (radeon_is_debug_enabled(type, level)) {		\
118		_radeon_print(_debug_type, _debug_level,	\
119			__VA_ARGS__);				\
120	}							\
121} while(0)
122
123/**
124 * printf style function for writing error messages.
125 */
126#define radeon_error(...) do {					\
127	radeon_print(RADEON_GENERAL, RADEON_CRITICAL,		\
128		__VA_ARGS__);					\
129} while(0)
130
131/**
132 * printf style function for writing warnings.
133 */
134#define radeon_warning(...) do {				\
135	radeon_print(RADEON_GENERAL, RADEON_IMPORTANT,		\
136		__VA_ARGS__);					\
137} while(0)
138
139extern void radeon_init_debug(void);
140extern void _radeon_debug_add_indent(void);
141extern void _radeon_debug_remove_indent(void);
142
143static inline void radeon_debug_add_indent(void)
144{
145       if (RADEON_DEBUG_LEVEL >= RADEON_VERBOSE) {
146	      _radeon_debug_add_indent();
147       }
148}
149static inline void radeon_debug_remove_indent(void)
150{
151       if (RADEON_DEBUG_LEVEL >= RADEON_VERBOSE) {
152	      _radeon_debug_remove_indent();
153       }
154}
155
156
157/* From http://gcc. gnu.org/onlinedocs/gcc-3.2.3/gcc/Variadic-Macros.html .
158   I suppose we could inline this and use macro to fetch out __LINE__ and stuff in case we run into trouble
159   with other compilers ... GLUE!
160*/
161#define WARN_ONCE(...)      do { \
162       static int __warn_once=1; \
163       if(__warn_once){ \
164               radeon_warning("*********************************WARN_ONCE*********************************\n"); \
165               radeon_warning("File %s function %s line %d\n", \
166                       __FILE__, __FUNCTION__, __LINE__); \
167               radeon_warning(__VA_ARGS__);\
168               radeon_warning("***************************************************************************\n"); \
169               __warn_once=0;\
170               } \
171       } while(0)
172
173
174#endif
175