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.
35 #include "util/imports.h"
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_vdebugf(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_debugf(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_vdebugf(ctx
, id
, source
, type
, severity
, fmtString
, args
);
257 _mesa_gl_debug(struct gl_context
*ctx
,
259 enum mesa_debug_source source
,
260 enum mesa_debug_type type
,
261 enum mesa_debug_severity severity
,
264 _mesa_debug_get_id(id
);
266 size_t len
= strnlen(msg
, MAX_DEBUG_MESSAGE_LENGTH
);
267 if (len
< MAX_DEBUG_MESSAGE_LENGTH
) {
268 _mesa_log_msg(ctx
, source
, type
, *id
, severity
, len
, msg
);
272 /* limit the message to fit within KHR_debug buffers */
273 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
274 strncpy(s
, msg
, MAX_DEBUG_MESSAGE_LENGTH
);
275 s
[MAX_DEBUG_MESSAGE_LENGTH
- 1] = '\0';
276 len
= MAX_DEBUG_MESSAGE_LENGTH
- 1;
277 _mesa_log_msg(ctx
, source
, type
, *id
, severity
, len
, s
);
279 /* report the number of characters that were logged */
285 * Record an OpenGL state error. These usually occur when the user
286 * passes invalid parameters to a GL function.
288 * If debugging is enabled (either at compile-time via the DEBUG macro, or
289 * run-time via the MESA_DEBUG environment variable), report the error with
292 * \param ctx the GL context.
293 * \param error the error value.
294 * \param fmtString printf() style format string, followed by optional args
297 _mesa_error( struct gl_context
*ctx
, GLenum error
, const char *fmtString
, ... )
299 GLboolean do_output
, do_log
;
300 /* Ideally this would be set up by the caller, so that we had proper IDs
301 * per different message.
303 static GLuint error_msg_id
= 0;
305 _mesa_debug_get_id(&error_msg_id
);
307 do_output
= should_output(ctx
, error
, fmtString
);
309 simple_mtx_lock(&ctx
->DebugMutex
);
311 do_log
= _mesa_debug_is_message_enabled(ctx
->Debug
,
312 MESA_DEBUG_SOURCE_API
,
313 MESA_DEBUG_TYPE_ERROR
,
315 MESA_DEBUG_SEVERITY_HIGH
);
320 simple_mtx_unlock(&ctx
->DebugMutex
);
322 if (do_output
|| do_log
) {
323 char s
[MAX_DEBUG_MESSAGE_LENGTH
], s2
[MAX_DEBUG_MESSAGE_LENGTH
];
327 va_start(args
, fmtString
);
328 len
= _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
331 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
) {
332 /* Too long error message. Whoever calls _mesa_error should use
339 len
= _mesa_snprintf(s2
, MAX_DEBUG_MESSAGE_LENGTH
, "%s in %s",
340 _mesa_enum_to_string(error
), s
);
341 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
) {
347 /* Print the error to stderr if needed. */
349 output_if_debug("Mesa: User error", s2
, GL_TRUE
);
352 /* Log the error via ARB_debug_output if needed.*/
354 _mesa_log_msg(ctx
, MESA_DEBUG_SOURCE_API
, MESA_DEBUG_TYPE_ERROR
,
355 error_msg_id
, MESA_DEBUG_SEVERITY_HIGH
, len
, s2
);
359 /* Set the GL context error state for glGetError. */
360 if (ctx
->ErrorValue
== GL_NO_ERROR
)
361 ctx
->ErrorValue
= error
;
365 _mesa_error_no_memory(const char *caller
)
367 GET_CURRENT_CONTEXT(ctx
);
368 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "out of memory in %s", caller
);
372 * Report debug information. Print error message to stderr via fprintf().
373 * No-op if DEBUG mode not enabled.
375 * \param ctx GL context.
376 * \param fmtString printf()-style format string, followed by optional args.
379 _mesa_debug( const struct gl_context
*ctx
, const char *fmtString
, ... )
382 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
384 va_start(args
, fmtString
);
385 _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
387 output_if_debug("Mesa", s
, GL_FALSE
);
395 _mesa_log(const char *fmtString
, ...)
397 char s
[MAX_DEBUG_MESSAGE_LENGTH
];
399 va_start(args
, fmtString
);
400 _mesa_vsnprintf(s
, MAX_DEBUG_MESSAGE_LENGTH
, fmtString
, args
);
402 output_if_debug("", s
, GL_FALSE
);
407 * Report debug information from the shader compiler via GL_ARB_debug_output.
409 * \param ctx GL context.
410 * \param type The namespace to which this message belongs.
411 * \param id The message ID within the given namespace.
412 * \param msg The message to output. Must be null-terminated.
415 _mesa_shader_debug(struct gl_context
*ctx
, GLenum type
, GLuint
*id
,
418 enum mesa_debug_source source
= MESA_DEBUG_SOURCE_SHADER_COMPILER
;
419 enum mesa_debug_severity severity
= MESA_DEBUG_SEVERITY_HIGH
;
422 _mesa_debug_get_id(id
);
426 /* Truncate the message if necessary. */
427 if (len
>= MAX_DEBUG_MESSAGE_LENGTH
)
428 len
= MAX_DEBUG_MESSAGE_LENGTH
- 1;
430 _mesa_log_msg(ctx
, source
, type
, *id
, severity
, len
, msg
);