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 " PACKAGE_VERSION
" implementation error: %s\n",
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
);
234 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
)
235 /* message was truncated */
236 len
= MAX_DEBUG_MESSAGE_LENGTH
- 1;
238 _mesa_log_msg(ctx
, source
, type
, *id
, severity
, len
, s
);
243 _mesa_gl_debug(struct gl_context
*ctx
,
245 enum mesa_debug_source source
,
246 enum mesa_debug_type type
,
247 enum mesa_debug_severity severity
,
248 const char *fmtString
, ...)
251 va_start(args
, fmtString
);
252 _mesa_gl_vdebug(ctx
, id
, source
, type
, severity
, fmtString
, args
);
258 * Record an OpenGL state error. These usually occur when the user
259 * passes invalid parameters to a GL function.
261 * If debugging is enabled (either at compile-time via the DEBUG macro, or
262 * run-time via the MESA_DEBUG environment variable), report the error with
265 * \param ctx the GL context.
266 * \param error the error value.
267 * \param fmtString printf() style format string, followed by optional args
270 _mesa_error( struct gl_context
*ctx
, GLenum error
, const char *fmtString
, ... )
272 GLboolean do_output
, do_log
;
273 /* Ideally this would be set up by the caller, so that we had proper IDs
274 * per different message.
276 static GLuint error_msg_id
= 0;
278 _mesa_debug_get_id(&error_msg_id
);
280 do_output
= should_output(ctx
, error
, fmtString
);
282 simple_mtx_lock(&ctx
->DebugMutex
);
284 do_log
= _mesa_debug_is_message_enabled(ctx
->Debug
,
285 MESA_DEBUG_SOURCE_API
,
286 MESA_DEBUG_TYPE_ERROR
,
288 MESA_DEBUG_SEVERITY_HIGH
);
293 simple_mtx_unlock(&ctx
->DebugMutex
);
295 if (do_output
|| do_log
) {
296 char s
[MAX_DEBUG_MESSAGE_LENGTH
], s2
[MAX_DEBUG_MESSAGE_LENGTH
];
300 va_start(args
, fmtString
);
301 len
= _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
304 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
) {
305 /* Too long error message. Whoever calls _mesa_error should use
312 len
= _mesa_snprintf(s2
, MAX_DEBUG_MESSAGE_LENGTH
, "%s in %s",
313 _mesa_enum_to_string(error
), s
);
314 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
) {
320 /* Print the error to stderr if needed. */
322 output_if_debug("Mesa: User error", s2
, GL_TRUE
);
325 /* Log the error via ARB_debug_output if needed.*/
327 _mesa_log_msg(ctx
, MESA_DEBUG_SOURCE_API
, MESA_DEBUG_TYPE_ERROR
,
328 error_msg_id
, MESA_DEBUG_SEVERITY_HIGH
, len
, s2
);
332 /* Set the GL context error state for glGetError. */
333 if (ctx
->ErrorValue
== GL_NO_ERROR
)
334 ctx
->ErrorValue
= error
;
338 _mesa_error_no_memory(const char *caller
)
340 GET_CURRENT_CONTEXT(ctx
);
341 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "out of memory in %s", caller
);
345 * Report debug information. Print error message to stderr via fprintf().
346 * No-op if DEBUG mode not enabled.
348 * \param ctx GL context.
349 * \param fmtString printf()-style format string, followed by optional args.
352 _mesa_debug( const struct gl_context
*ctx
, const char *fmtString
, ... )
355 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
357 va_start(args
, fmtString
);
358 _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
360 output_if_debug("Mesa", s
, GL_FALSE
);
368 _mesa_log(const char *fmtString
, ...)
370 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
372 va_start(args
, fmtString
);
373 _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
375 output_if_debug("", s
, GL_FALSE
);
380 * Report debug information from the shader compiler via GL_ARB_debug_output.
382 * \param ctx GL context.
383 * \param type The namespace to which this message belongs.
384 * \param id The message ID within the given namespace.
385 * \param msg The message to output. Must be null-terminated.
388 _mesa_shader_debug(struct gl_context
*ctx
, GLenum type
, GLuint
*id
,
391 enum mesa_debug_source source
= MESA_DEBUG_SOURCE_SHADER_COMPILER
;
392 enum mesa_debug_severity severity
= MESA_DEBUG_SEVERITY_HIGH
;
395 _mesa_debug_get_id(id
);
399 /* Truncate the message if necessary. */
400 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
)
401 len
= MAX_DEBUG_MESSAGE_LENGTH
- 1;
403 _mesa_log_msg(ctx
, source
, type
, *id
, severity
, len
, msg
);