1848b8605Smrg/**
2848b8605Smrg * \file errors.c
3848b8605Smrg * Mesa debugging and error handling functions.
4848b8605Smrg */
5848b8605Smrg
6848b8605Smrg/*
7848b8605Smrg * Mesa 3-D graphics library
8848b8605Smrg *
9848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
10848b8605Smrg *
11848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
12848b8605Smrg * copy of this software and associated documentation files (the "Software"),
13848b8605Smrg * to deal in the Software without restriction, including without limitation
14848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
16848b8605Smrg * Software is furnished to do so, subject to the following conditions:
17848b8605Smrg *
18848b8605Smrg * The above copyright notice and this permission notice shall be included
19848b8605Smrg * in all copies or substantial portions of the Software.
20848b8605Smrg *
21848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
28848b8605Smrg */
29848b8605Smrg
30848b8605Smrg
31b8e80941Smrg#include <stdarg.h>
32b8e80941Smrg#include <stdio.h>
33848b8605Smrg#include "errors.h"
34848b8605Smrg#include "enums.h"
35848b8605Smrg#include "imports.h"
36848b8605Smrg#include "context.h"
37b8e80941Smrg#include "debug_output.h"
38848b8605Smrg
39848b8605Smrg
40b8e80941Smrgstatic FILE *LogFile = NULL;
41848b8605Smrg
42848b8605Smrg
43848b8605Smrgstatic void
44848b8605Smrgoutput_if_debug(const char *prefixString, const char *outputString,
45848b8605Smrg                GLboolean newline)
46848b8605Smrg{
47848b8605Smrg   static int debug = -1;
48848b8605Smrg
49848b8605Smrg   /* Init the local 'debug' var once.
50848b8605Smrg    * Note: the _mesa_init_debug() function should have been called
51848b8605Smrg    * by now so MESA_DEBUG_FLAGS will be initialized.
52848b8605Smrg    */
53848b8605Smrg   if (debug == -1) {
54848b8605Smrg      /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
55848b8605Smrg       * etc to the named file.  Otherwise, output to stderr.
56848b8605Smrg       */
57b8e80941Smrg      const char *logFile = getenv("MESA_LOG_FILE");
58848b8605Smrg      if (logFile)
59b8e80941Smrg         LogFile = fopen(logFile, "w");
60b8e80941Smrg      if (!LogFile)
61b8e80941Smrg         LogFile = stderr;
62848b8605Smrg#ifdef DEBUG
63848b8605Smrg      /* in debug builds, print messages unless MESA_DEBUG="silent" */
64848b8605Smrg      if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
65848b8605Smrg         debug = 0;
66848b8605Smrg      else
67848b8605Smrg         debug = 1;
68848b8605Smrg#else
69848b8605Smrg      /* in release builds, be silent unless MESA_DEBUG is set */
70b8e80941Smrg      debug = getenv("MESA_DEBUG") != NULL;
71848b8605Smrg#endif
72848b8605Smrg   }
73848b8605Smrg
74848b8605Smrg   /* Now only print the string if we're required to do so. */
75848b8605Smrg   if (debug) {
76b8e80941Smrg      if (prefixString)
77b8e80941Smrg         fprintf(LogFile, "%s: %s", prefixString, outputString);
78b8e80941Smrg      else
79b8e80941Smrg         fprintf(LogFile, "%s", outputString);
80848b8605Smrg      if (newline)
81b8e80941Smrg         fprintf(LogFile, "\n");
82b8e80941Smrg      fflush(LogFile);
83848b8605Smrg
84b8e80941Smrg#if defined(_WIN32)
85848b8605Smrg      /* stderr from windows applications without console is not usually
86848b8605Smrg       * visible, so communicate with the debugger instead */
87848b8605Smrg      {
88848b8605Smrg         char buf[4096];
89848b8605Smrg         _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
90848b8605Smrg         OutputDebugStringA(buf);
91848b8605Smrg      }
92848b8605Smrg#endif
93848b8605Smrg   }
94848b8605Smrg}
95848b8605Smrg
96848b8605Smrg
97b8e80941Smrg/**
98b8e80941Smrg * Return the file handle to use for debug/logging.  Defaults to stderr
99b8e80941Smrg * unless MESA_LOG_FILE is defined.
100b8e80941Smrg */
101b8e80941SmrgFILE *
102b8e80941Smrg_mesa_get_log_file(void)
103b8e80941Smrg{
104b8e80941Smrg   assert(LogFile);
105b8e80941Smrg   return LogFile;
106b8e80941Smrg}
107b8e80941Smrg
108b8e80941Smrg
109848b8605Smrg/**
110848b8605Smrg * When a new type of error is recorded, print a message describing
111848b8605Smrg * previous errors which were accumulated.
112848b8605Smrg */
113848b8605Smrgstatic void
114848b8605Smrgflush_delayed_errors( struct gl_context *ctx )
115848b8605Smrg{
116848b8605Smrg   char s[MAX_DEBUG_MESSAGE_LENGTH];
117848b8605Smrg
118848b8605Smrg   if (ctx->ErrorDebugCount) {
119b8e80941Smrg      _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors",
120848b8605Smrg                     ctx->ErrorDebugCount,
121b8e80941Smrg                     _mesa_enum_to_string(ctx->ErrorValue));
122848b8605Smrg
123848b8605Smrg      output_if_debug("Mesa", s, GL_TRUE);
124848b8605Smrg
125848b8605Smrg      ctx->ErrorDebugCount = 0;
126848b8605Smrg   }
127848b8605Smrg}
128848b8605Smrg
129848b8605Smrg
130848b8605Smrg/**
131848b8605Smrg * Report a warning (a recoverable error condition) to stderr if
132848b8605Smrg * either DEBUG is defined or the MESA_DEBUG env var is set.
133848b8605Smrg *
134848b8605Smrg * \param ctx GL context.
135848b8605Smrg * \param fmtString printf()-like format string.
136848b8605Smrg */
137848b8605Smrgvoid
138848b8605Smrg_mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
139848b8605Smrg{
140848b8605Smrg   char str[MAX_DEBUG_MESSAGE_LENGTH];
141848b8605Smrg   va_list args;
142b8e80941Smrg   va_start( args, fmtString );
143848b8605Smrg   (void) _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
144848b8605Smrg   va_end( args );
145b8e80941Smrg
146848b8605Smrg   if (ctx)
147848b8605Smrg      flush_delayed_errors( ctx );
148848b8605Smrg
149848b8605Smrg   output_if_debug("Mesa warning", str, GL_TRUE);
150848b8605Smrg}
151848b8605Smrg
152848b8605Smrg
153848b8605Smrg/**
154848b8605Smrg * Report an internal implementation problem.
155848b8605Smrg * Prints the message to stderr via fprintf().
156848b8605Smrg *
157848b8605Smrg * \param ctx GL context.
158848b8605Smrg * \param fmtString problem description string.
159848b8605Smrg */
160848b8605Smrgvoid
161848b8605Smrg_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
162848b8605Smrg{
163848b8605Smrg   va_list args;
164848b8605Smrg   char str[MAX_DEBUG_MESSAGE_LENGTH];
165848b8605Smrg   static int numCalls = 0;
166848b8605Smrg
167848b8605Smrg   (void) ctx;
168848b8605Smrg
169848b8605Smrg   if (numCalls < 50) {
170848b8605Smrg      numCalls++;
171848b8605Smrg
172b8e80941Smrg      va_start( args, fmtString );
173848b8605Smrg      _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
174848b8605Smrg      va_end( args );
175b8e80941Smrg      fprintf(stderr, "Mesa " PACKAGE_VERSION " implementation error: %s\n",
176b8e80941Smrg              str);
177848b8605Smrg      fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n");
178848b8605Smrg   }
179848b8605Smrg}
180848b8605Smrg
181848b8605Smrg
182848b8605Smrgstatic GLboolean
183848b8605Smrgshould_output(struct gl_context *ctx, GLenum error, const char *fmtString)
184848b8605Smrg{
185848b8605Smrg   static GLint debug = -1;
186848b8605Smrg
187848b8605Smrg   /* Check debug environment variable only once:
188848b8605Smrg    */
189848b8605Smrg   if (debug == -1) {
190b8e80941Smrg      const char *debugEnv = getenv("MESA_DEBUG");
191848b8605Smrg
192848b8605Smrg#ifdef DEBUG
193848b8605Smrg      if (debugEnv && strstr(debugEnv, "silent"))
194848b8605Smrg         debug = GL_FALSE;
195848b8605Smrg      else
196848b8605Smrg         debug = GL_TRUE;
197848b8605Smrg#else
198848b8605Smrg      if (debugEnv)
199848b8605Smrg         debug = GL_TRUE;
200848b8605Smrg      else
201848b8605Smrg         debug = GL_FALSE;
202848b8605Smrg#endif
203848b8605Smrg   }
204848b8605Smrg
205848b8605Smrg   if (debug) {
206848b8605Smrg      if (ctx->ErrorValue != error ||
207848b8605Smrg          ctx->ErrorDebugFmtString != fmtString) {
208848b8605Smrg         flush_delayed_errors( ctx );
209848b8605Smrg         ctx->ErrorDebugFmtString = fmtString;
210848b8605Smrg         ctx->ErrorDebugCount = 0;
211848b8605Smrg         return GL_TRUE;
212848b8605Smrg      }
213848b8605Smrg      ctx->ErrorDebugCount++;
214848b8605Smrg   }
215848b8605Smrg   return GL_FALSE;
216848b8605Smrg}
217848b8605Smrg
218848b8605Smrg
219848b8605Smrgvoid
220b8e80941Smrg_mesa_gl_vdebugf(struct gl_context *ctx,
221b8e80941Smrg                 GLuint *id,
222b8e80941Smrg                 enum mesa_debug_source source,
223b8e80941Smrg                 enum mesa_debug_type type,
224b8e80941Smrg                 enum mesa_debug_severity severity,
225b8e80941Smrg                 const char *fmtString,
226b8e80941Smrg                 va_list args)
227848b8605Smrg{
228848b8605Smrg   char s[MAX_DEBUG_MESSAGE_LENGTH];
229848b8605Smrg   int len;
230848b8605Smrg
231b8e80941Smrg   _mesa_debug_get_id(id);
232848b8605Smrg
233848b8605Smrg   len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
234b8e80941Smrg   if (len >= MAX_DEBUG_MESSAGE_LENGTH)
235b8e80941Smrg      /* message was truncated */
236b8e80941Smrg      len = MAX_DEBUG_MESSAGE_LENGTH - 1;
237b8e80941Smrg
238b8e80941Smrg   _mesa_log_msg(ctx, source, type, *id, severity, len, s);
239b8e80941Smrg}
240b8e80941Smrg
241b8e80941Smrg
242b8e80941Smrgvoid
243b8e80941Smrg_mesa_gl_debugf(struct gl_context *ctx,
244b8e80941Smrg                GLuint *id,
245b8e80941Smrg                enum mesa_debug_source source,
246b8e80941Smrg                enum mesa_debug_type type,
247b8e80941Smrg                enum mesa_debug_severity severity,
248b8e80941Smrg                const char *fmtString, ...)
249b8e80941Smrg{
250b8e80941Smrg   va_list args;
251b8e80941Smrg   va_start(args, fmtString);
252b8e80941Smrg   _mesa_gl_vdebugf(ctx, id, source, type, severity, fmtString, args);
253848b8605Smrg   va_end(args);
254b8e80941Smrg}
255b8e80941Smrg
256b8e80941Smrgsize_t
257b8e80941Smrg_mesa_gl_debug(struct gl_context *ctx,
258b8e80941Smrg               GLuint *id,
259b8e80941Smrg               enum mesa_debug_source source,
260b8e80941Smrg               enum mesa_debug_type type,
261b8e80941Smrg               enum mesa_debug_severity severity,
262b8e80941Smrg               const char *msg)
263b8e80941Smrg{
264b8e80941Smrg   _mesa_debug_get_id(id);
265848b8605Smrg
266b8e80941Smrg   size_t len = strnlen(msg, MAX_DEBUG_MESSAGE_LENGTH);
267b8e80941Smrg   if (len < MAX_DEBUG_MESSAGE_LENGTH) {
268b8e80941Smrg      _mesa_log_msg(ctx, source, type, *id, severity, len, msg);
269b8e80941Smrg      return len;
270b8e80941Smrg   }
271b8e80941Smrg
272b8e80941Smrg   /* limit the message to fit within KHR_debug buffers */
273b8e80941Smrg   char s[MAX_DEBUG_MESSAGE_LENGTH];
274b8e80941Smrg   strncpy(s, msg, MAX_DEBUG_MESSAGE_LENGTH);
275b8e80941Smrg   s[MAX_DEBUG_MESSAGE_LENGTH - 1] = '\0';
276b8e80941Smrg   len = MAX_DEBUG_MESSAGE_LENGTH - 1;
277b8e80941Smrg   _mesa_log_msg(ctx, source, type, *id, severity, len, s);
278b8e80941Smrg
279b8e80941Smrg   /* report the number of characters that were logged */
280b8e80941Smrg   return len;
281848b8605Smrg}
282848b8605Smrg
283848b8605Smrg
284848b8605Smrg/**
285848b8605Smrg * Record an OpenGL state error.  These usually occur when the user
286848b8605Smrg * passes invalid parameters to a GL function.
287848b8605Smrg *
288848b8605Smrg * If debugging is enabled (either at compile-time via the DEBUG macro, or
289848b8605Smrg * run-time via the MESA_DEBUG environment variable), report the error with
290848b8605Smrg * _mesa_debug().
291b8e80941Smrg *
292848b8605Smrg * \param ctx the GL context.
293848b8605Smrg * \param error the error value.
294848b8605Smrg * \param fmtString printf() style format string, followed by optional args
295848b8605Smrg */
296848b8605Smrgvoid
297848b8605Smrg_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
298848b8605Smrg{
299848b8605Smrg   GLboolean do_output, do_log;
300848b8605Smrg   /* Ideally this would be set up by the caller, so that we had proper IDs
301848b8605Smrg    * per different message.
302848b8605Smrg    */
303848b8605Smrg   static GLuint error_msg_id = 0;
304848b8605Smrg
305b8e80941Smrg   _mesa_debug_get_id(&error_msg_id);
306848b8605Smrg
307848b8605Smrg   do_output = should_output(ctx, error, fmtString);
308b8e80941Smrg
309b8e80941Smrg   simple_mtx_lock(&ctx->DebugMutex);
310848b8605Smrg   if (ctx->Debug) {
311b8e80941Smrg      do_log = _mesa_debug_is_message_enabled(ctx->Debug,
312b8e80941Smrg                                              MESA_DEBUG_SOURCE_API,
313b8e80941Smrg                                              MESA_DEBUG_TYPE_ERROR,
314b8e80941Smrg                                              error_msg_id,
315b8e80941Smrg                                              MESA_DEBUG_SEVERITY_HIGH);
316848b8605Smrg   }
317848b8605Smrg   else {
318848b8605Smrg      do_log = GL_FALSE;
319848b8605Smrg   }
320b8e80941Smrg   simple_mtx_unlock(&ctx->DebugMutex);
321848b8605Smrg
322848b8605Smrg   if (do_output || do_log) {
323848b8605Smrg      char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
324848b8605Smrg      int len;
325848b8605Smrg      va_list args;
326848b8605Smrg
327848b8605Smrg      va_start(args, fmtString);
328848b8605Smrg      len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
329848b8605Smrg      va_end(args);
330848b8605Smrg
331848b8605Smrg      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
332848b8605Smrg         /* Too long error message. Whoever calls _mesa_error should use
333848b8605Smrg          * shorter strings.
334848b8605Smrg          */
335b8e80941Smrg         assert(0);
336848b8605Smrg         return;
337848b8605Smrg      }
338848b8605Smrg
339848b8605Smrg      len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
340b8e80941Smrg                           _mesa_enum_to_string(error), s);
341848b8605Smrg      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
342848b8605Smrg         /* Same as above. */
343b8e80941Smrg         assert(0);
344848b8605Smrg         return;
345848b8605Smrg      }
346848b8605Smrg
347848b8605Smrg      /* Print the error to stderr if needed. */
348848b8605Smrg      if (do_output) {
349848b8605Smrg         output_if_debug("Mesa: User error", s2, GL_TRUE);
350848b8605Smrg      }
351848b8605Smrg
352848b8605Smrg      /* Log the error via ARB_debug_output if needed.*/
353848b8605Smrg      if (do_log) {
354b8e80941Smrg         _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR,
355b8e80941Smrg                       error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2);
356848b8605Smrg      }
357848b8605Smrg   }
358848b8605Smrg
359848b8605Smrg   /* Set the GL context error state for glGetError. */
360b8e80941Smrg   if (ctx->ErrorValue == GL_NO_ERROR)
361b8e80941Smrg      ctx->ErrorValue = error;
362848b8605Smrg}
363848b8605Smrg
364848b8605Smrgvoid
365848b8605Smrg_mesa_error_no_memory(const char *caller)
366848b8605Smrg{
367848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
368848b8605Smrg   _mesa_error(ctx, GL_OUT_OF_MEMORY, "out of memory in %s", caller);
369848b8605Smrg}
370848b8605Smrg
371848b8605Smrg/**
372848b8605Smrg * Report debug information.  Print error message to stderr via fprintf().
373848b8605Smrg * No-op if DEBUG mode not enabled.
374b8e80941Smrg *
375848b8605Smrg * \param ctx GL context.
376848b8605Smrg * \param fmtString printf()-style format string, followed by optional args.
377848b8605Smrg */
378848b8605Smrgvoid
379848b8605Smrg_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
380848b8605Smrg{
381848b8605Smrg#ifdef DEBUG
382848b8605Smrg   char s[MAX_DEBUG_MESSAGE_LENGTH];
383848b8605Smrg   va_list args;
384848b8605Smrg   va_start(args, fmtString);
385848b8605Smrg   _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
386848b8605Smrg   va_end(args);
387848b8605Smrg   output_if_debug("Mesa", s, GL_FALSE);
388848b8605Smrg#endif /* DEBUG */
389848b8605Smrg   (void) ctx;
390848b8605Smrg   (void) fmtString;
391848b8605Smrg}
392848b8605Smrg
393848b8605Smrg
394b8e80941Smrgvoid
395b8e80941Smrg_mesa_log(const char *fmtString, ...)
396b8e80941Smrg{
397b8e80941Smrg   char s[MAX_DEBUG_MESSAGE_LENGTH];
398b8e80941Smrg   va_list args;
399b8e80941Smrg   va_start(args, fmtString);
400b8e80941Smrg   _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
401b8e80941Smrg   va_end(args);
402b8e80941Smrg   output_if_debug("", s, GL_FALSE);
403b8e80941Smrg}
404b8e80941Smrg
405b8e80941Smrg
406848b8605Smrg/**
407848b8605Smrg * Report debug information from the shader compiler via GL_ARB_debug_output.
408848b8605Smrg *
409848b8605Smrg * \param ctx GL context.
410848b8605Smrg * \param type The namespace to which this message belongs.
411848b8605Smrg * \param id The message ID within the given namespace.
412b8e80941Smrg * \param msg The message to output. Must be null-terminated.
413848b8605Smrg */
414848b8605Smrgvoid
415b8e80941Smrg_mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id,
416b8e80941Smrg                   const char *msg)
417848b8605Smrg{
418848b8605Smrg   enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
419848b8605Smrg   enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH;
420b8e80941Smrg   int len;
421848b8605Smrg
422b8e80941Smrg   _mesa_debug_get_id(id);
423848b8605Smrg
424b8e80941Smrg   len = strlen(msg);
425848b8605Smrg
426848b8605Smrg   /* Truncate the message if necessary. */
427848b8605Smrg   if (len >= MAX_DEBUG_MESSAGE_LENGTH)
428848b8605Smrg      len = MAX_DEBUG_MESSAGE_LENGTH - 1;
429848b8605Smrg
430b8e80941Smrg   _mesa_log_msg(ctx, source, type, *id, severity, len, msg);
431848b8605Smrg}
432