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 # define LOG_TAG "mesa"
44 static FILE *LogFile = NULL;
48 output_if_debug(const char *prefixString, const char *outputString,
51 static int debug = -1;
53 /* Init the local 'debug' var once.
54 * Note: the _mesa_init_debug() function should have been called
55 * by now so MESA_DEBUG_FLAGS will be initialized.
58 /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
59 * etc to the named file. Otherwise, output to stderr.
61 const char *logFile = getenv("MESA_LOG_FILE");
63 LogFile = fopen(logFile, "w");
67 /* in debug builds, print messages unless MESA_DEBUG="silent" */
68 if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
73 /* in release builds, be silent unless MESA_DEBUG is set */
74 debug = getenv("MESA_DEBUG") != NULL;
78 /* Now only print the string if we're required to do so. */
81 fprintf(LogFile, "%s: %s", prefixString, outputString);
83 fprintf(LogFile, "%s", outputString);
85 fprintf(LogFile, "\n");
89 /* stderr from windows applications without console is not usually
90 * visible, so communicate with the debugger instead */
93 _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
94 OutputDebugStringA(buf);
96 #elif defined(ANDROID)
98 ALOGD("%s: %s", prefixString, outputString);
106 * Return the file handle to use for debug/logging. Defaults to stderr
107 * unless MESA_LOG_FILE is defined.
110 _mesa_get_log_file(void)
118 * When a new type of error is recorded, print a message describing
119 * previous errors which were accumulated.
122 flush_delayed_errors( struct gl_context *ctx )
124 char s[MAX_DEBUG_MESSAGE_LENGTH];
126 if (ctx->ErrorDebugCount) {
127 _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors",
128 ctx->ErrorDebugCount,
129 _mesa_enum_to_string(ctx->ErrorValue));
131 output_if_debug("Mesa", s, GL_TRUE);
133 ctx->ErrorDebugCount = 0;
139 * Report a warning (a recoverable error condition) to stderr if
140 * either DEBUG is defined or the MESA_DEBUG env var is set.
142 * \param ctx GL context.
143 * \param fmtString printf()-like format string.
146 _mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
148 char str[MAX_DEBUG_MESSAGE_LENGTH];
150 va_start( args, fmtString );
151 (void) _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
155 flush_delayed_errors( ctx );
157 output_if_debug("Mesa warning", str, GL_TRUE);
162 * Report an internal implementation problem.
163 * Prints the message to stderr via fprintf().
165 * \param ctx GL context.
166 * \param fmtString problem description string.
169 _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
172 char str[MAX_DEBUG_MESSAGE_LENGTH];
173 static int numCalls = 0;
180 va_start( args, fmtString );
181 _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
183 fprintf(stderr, "Mesa " PACKAGE_VERSION " implementation error: %s\n",
185 fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n");
191 should_output(struct gl_context *ctx, GLenum error, const char *fmtString)
193 static GLint debug = -1;
195 /* Check debug environment variable only once:
198 const char *debugEnv = getenv("MESA_DEBUG");
201 if (debugEnv && strstr(debugEnv, "silent"))
214 if (ctx->ErrorValue != error ||
215 ctx->ErrorDebugFmtString != fmtString) {
216 flush_delayed_errors( ctx );
217 ctx->ErrorDebugFmtString = fmtString;
218 ctx->ErrorDebugCount = 0;
221 ctx->ErrorDebugCount++;
228 _mesa_gl_vdebug(struct gl_context *ctx,
230 enum mesa_debug_source source,
231 enum mesa_debug_type type,
232 enum mesa_debug_severity severity,
233 const char *fmtString,
236 char s[MAX_DEBUG_MESSAGE_LENGTH];
239 _mesa_debug_get_id(id);
241 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
242 if (len >= MAX_DEBUG_MESSAGE_LENGTH)
243 /* message was truncated */
244 len = MAX_DEBUG_MESSAGE_LENGTH - 1;
246 _mesa_log_msg(ctx, source, type, *id, severity, len, s);
251 _mesa_gl_debug(struct gl_context *ctx,
253 enum mesa_debug_source source,
254 enum mesa_debug_type type,
255 enum mesa_debug_severity severity,
256 const char *fmtString, ...)
259 va_start(args, fmtString);
260 _mesa_gl_vdebug(ctx, id, source, type, severity, fmtString, args);
266 * Record an OpenGL state error. These usually occur when the user
267 * passes invalid parameters to a GL function.
269 * If debugging is enabled (either at compile-time via the DEBUG macro, or
270 * run-time via the MESA_DEBUG environment variable), report the error with
273 * \param ctx the GL context.
274 * \param error the error value.
275 * \param fmtString printf() style format string, followed by optional args
278 _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
280 GLboolean do_output, do_log;
281 /* Ideally this would be set up by the caller, so that we had proper IDs
282 * per different message.
284 static GLuint error_msg_id = 0;
286 _mesa_debug_get_id(&error_msg_id);
288 do_output = should_output(ctx, error, fmtString);
290 simple_mtx_lock(&ctx->DebugMutex);
292 do_log = _mesa_debug_is_message_enabled(ctx->Debug,
293 MESA_DEBUG_SOURCE_API,
294 MESA_DEBUG_TYPE_ERROR,
296 MESA_DEBUG_SEVERITY_HIGH);
301 simple_mtx_unlock(&ctx->DebugMutex);
303 if (do_output || do_log) {
304 char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
308 va_start(args, fmtString);
309 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
312 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
313 /* Too long error message. Whoever calls _mesa_error should use
320 len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
321 _mesa_enum_to_string(error), s);
322 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
328 /* Print the error to stderr if needed. */
330 output_if_debug("Mesa: User error", s2, GL_TRUE);
333 /* Log the error via ARB_debug_output if needed.*/
335 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR,
336 error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2);
340 /* Set the GL context error state for glGetError. */
341 if (ctx->ErrorValue == GL_NO_ERROR)
342 ctx->ErrorValue = error;
346 _mesa_error_no_memory(const char *caller)
348 GET_CURRENT_CONTEXT(ctx);
349 _mesa_error(ctx, GL_OUT_OF_MEMORY, "out of memory in %s", caller);
353 * Report debug information. Print error message to stderr via fprintf().
354 * No-op if DEBUG mode not enabled.
356 * \param ctx GL context.
357 * \param fmtString printf()-style format string, followed by optional args.
360 _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
363 char s[MAX_DEBUG_MESSAGE_LENGTH];
365 va_start(args, fmtString);
366 _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
368 output_if_debug("Mesa", s, GL_FALSE);
376 _mesa_log(const char *fmtString, ...)
378 char s[MAX_DEBUG_MESSAGE_LENGTH];
380 va_start(args, fmtString);
381 _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
383 output_if_debug("", s, GL_FALSE);
388 * Report debug information from the shader compiler via GL_ARB_debug_output.
390 * \param ctx GL context.
391 * \param type The namespace to which this message belongs.
392 * \param id The message ID within the given namespace.
393 * \param msg The message to output. Must be null-terminated.
396 _mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id,
399 enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
400 enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH;
403 _mesa_debug_get_id(id);
407 /* Truncate the message if necessary. */
408 if (len >= MAX_DEBUG_MESSAGE_LENGTH)
409 len = MAX_DEBUG_MESSAGE_LENGTH - 1;
411 _mesa_log_msg(ctx, source, type, *id, severity, len, msg);