3 * Mesa debugging and error handling functions.
7 * Mesa 3-D graphics library
9 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
37 #include "debug_output.h"
40 static FILE *LogFile
= NULL
;
44 output_if_debug(const char *prefixString
, const char *outputString
,
47 static int debug
= -1;
49 /* Init the local 'debug' var once.
50 * Note: the _mesa_init_debug() function should have been called
51 * by now so MESA_DEBUG_FLAGS will be initialized.
54 /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
55 * etc to the named file. Otherwise, output to stderr.
57 const char *logFile
= getenv("MESA_LOG_FILE");
59 LogFile
= fopen(logFile
, "w");
63 /* in debug builds, print messages unless MESA_DEBUG="silent" */
64 if (MESA_DEBUG_FLAGS
& DEBUG_SILENT
)
69 /* in release builds, be silent unless MESA_DEBUG is set */
70 debug
= getenv("MESA_DEBUG") != NULL
;
74 /* Now only print the string if we're required to do so. */
77 fprintf(LogFile
, "%s: %s", prefixString
, outputString
);
79 fprintf(LogFile
, "%s", outputString
);
81 fprintf(LogFile
, "\n");
85 /* stderr from windows applications without console is not usually
86 * visible, so communicate with the debugger instead */
89 _mesa_snprintf(buf
, sizeof(buf
), "%s: %s%s", prefixString
, outputString
, newline
? "\n" : "");
90 OutputDebugStringA(buf
);
98 * Return the file handle to use for debug/logging. Defaults to stderr
99 * unless MESA_LOG_FILE is defined.
102 _mesa_get_log_file(void)
110 * When a new type of error is recorded, print a message describing
111 * previous errors which were accumulated.
114 flush_delayed_errors( struct gl_context
*ctx
)
116 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
118 if (ctx
->ErrorDebugCount
) {
119 _mesa_snprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, "%d similar %s errors",
120 ctx
->ErrorDebugCount
,
121 _mesa_enum_to_string(ctx
->ErrorValue
));
123 output_if_debug("Mesa", s
, GL_TRUE
);
125 ctx
->ErrorDebugCount
= 0;
131 * Report a warning (a recoverable error condition) to stderr if
132 * either DEBUG is defined or the MESA_DEBUG env var is set.
134 * \param ctx GL context.
135 * \param fmtString printf()-like format string.
138 _mesa_warning( struct gl_context
*ctx
, const char *fmtString
, ... )
140 char str
[MAX_DEBUG_MESSAGE_LENGTH
];
142 va_start( args
, fmtString
);
143 (void) _mesa_vsnprintf( str
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
147 flush_delayed_errors( ctx
);
149 output_if_debug("Mesa warning", str
, GL_TRUE
);
154 * Report an internal implementation problem.
155 * Prints the message to stderr via fprintf().
157 * \param ctx GL context.
158 * \param fmtString problem description string.
161 _mesa_problem( const struct gl_context
*ctx
, const char *fmtString
, ... )
164 char str
[MAX_DEBUG_MESSAGE_LENGTH
];
165 static int numCalls
= 0;
172 va_start( args
, fmtString
);
173 _mesa_vsnprintf( str
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
175 fprintf(stderr
, "Mesa %s implementation error: %s\n",
176 PACKAGE_VERSION
, str
);
177 fprintf(stderr
, "Please report at " PACKAGE_BUGREPORT
"\n");
183 should_output(struct gl_context
*ctx
, GLenum error
, const char *fmtString
)
185 static GLint debug
= -1;
187 /* Check debug environment variable only once:
190 const char *debugEnv
= getenv("MESA_DEBUG");
193 if (debugEnv
&& strstr(debugEnv
, "silent"))
206 if (ctx
->ErrorValue
!= error
||
207 ctx
->ErrorDebugFmtString
!= fmtString
) {
208 flush_delayed_errors( ctx
);
209 ctx
->ErrorDebugFmtString
= fmtString
;
210 ctx
->ErrorDebugCount
= 0;
213 ctx
->ErrorDebugCount
++;
220 _mesa_gl_vdebug(struct gl_context
*ctx
,
222 enum mesa_debug_source source
,
223 enum mesa_debug_type type
,
224 enum mesa_debug_severity severity
,
225 const char *fmtString
,
228 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
231 _mesa_debug_get_id(id
);
233 len
= _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
235 _mesa_log_msg(ctx
, source
, type
, *id
, severity
, len
, s
);
240 _mesa_gl_debug(struct gl_context
*ctx
,
242 enum mesa_debug_source source
,
243 enum mesa_debug_type type
,
244 enum mesa_debug_severity severity
,
245 const char *fmtString
, ...)
248 va_start(args
, fmtString
);
249 _mesa_gl_vdebug(ctx
, id
, source
, type
, severity
, fmtString
, args
);
255 * Record an OpenGL state error. These usually occur when the user
256 * passes invalid parameters to a GL function.
258 * If debugging is enabled (either at compile-time via the DEBUG macro, or
259 * run-time via the MESA_DEBUG environment variable), report the error with
262 * \param ctx the GL context.
263 * \param error the error value.
264 * \param fmtString printf() style format string, followed by optional args
267 _mesa_error( struct gl_context
*ctx
, GLenum error
, const char *fmtString
, ... )
269 GLboolean do_output
, do_log
;
270 /* Ideally this would be set up by the caller, so that we had proper IDs
271 * per different message.
273 static GLuint error_msg_id
= 0;
275 _mesa_debug_get_id(&error_msg_id
);
277 do_output
= should_output(ctx
, error
, fmtString
);
279 mtx_lock(&ctx
->DebugMutex
);
281 do_log
= _mesa_debug_is_message_enabled(ctx
->Debug
,
282 MESA_DEBUG_SOURCE_API
,
283 MESA_DEBUG_TYPE_ERROR
,
285 MESA_DEBUG_SEVERITY_HIGH
);
290 mtx_unlock(&ctx
->DebugMutex
);
292 if (do_output
|| do_log
) {
293 char s
[MAX_DEBUG_MESSAGE_LENGTH
], s2
[MAX_DEBUG_MESSAGE_LENGTH
];
297 va_start(args
, fmtString
);
298 len
= _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
301 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
) {
302 /* Too long error message. Whoever calls _mesa_error should use
309 len
= _mesa_snprintf(s2
, MAX_DEBUG_MESSAGE_LENGTH
, "%s in %s",
310 _mesa_enum_to_string(error
), s
);
311 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
) {
317 /* Print the error to stderr if needed. */
319 output_if_debug("Mesa: User error", s2
, GL_TRUE
);
322 /* Log the error via ARB_debug_output if needed.*/
324 _mesa_log_msg(ctx
, MESA_DEBUG_SOURCE_API
, MESA_DEBUG_TYPE_ERROR
,
325 error_msg_id
, MESA_DEBUG_SEVERITY_HIGH
, len
, s2
);
329 /* Set the GL context error state for glGetError. */
330 _mesa_record_error(ctx
, error
);
334 _mesa_error_no_memory(const char *caller
)
336 GET_CURRENT_CONTEXT(ctx
);
337 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "out of memory in %s", caller
);
341 * Report debug information. Print error message to stderr via fprintf().
342 * No-op if DEBUG mode not enabled.
344 * \param ctx GL context.
345 * \param fmtString printf()-style format string, followed by optional args.
348 _mesa_debug( const struct gl_context
*ctx
, const char *fmtString
, ... )
351 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
353 va_start(args
, fmtString
);
354 _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
356 output_if_debug("Mesa", s
, GL_FALSE
);
364 _mesa_log(const char *fmtString
, ...)
366 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
368 va_start(args
, fmtString
);
369 _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
371 output_if_debug("", s
, GL_FALSE
);
376 * Report debug information from the shader compiler via GL_ARB_debug_output.
378 * \param ctx GL context.
379 * \param type The namespace to which this message belongs.
380 * \param id The message ID within the given namespace.
381 * \param msg The message to output. Must be null-terminated.
384 _mesa_shader_debug(struct gl_context
*ctx
, GLenum type
, GLuint
*id
,
387 enum mesa_debug_source source
= MESA_DEBUG_SOURCE_SHADER_COMPILER
;
388 enum mesa_debug_severity severity
= MESA_DEBUG_SEVERITY_HIGH
;
391 _mesa_debug_get_id(id
);
395 /* Truncate the message if necessary. */
396 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
)
397 len
= MAX_DEBUG_MESSAGE_LENGTH
- 1;
399 _mesa_log_msg(ctx
, source
, type
, *id
, severity
, len
, msg
);