1bf215546Sopenharmony_ci/**
2bf215546Sopenharmony_ci * \file errors.c
3bf215546Sopenharmony_ci * Mesa debugging and error handling functions.
4bf215546Sopenharmony_ci */
5bf215546Sopenharmony_ci
6bf215546Sopenharmony_ci/*
7bf215546Sopenharmony_ci * Mesa 3-D graphics library
8bf215546Sopenharmony_ci *
9bf215546Sopenharmony_ci * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
12bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
13bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
14bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
16bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
19bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
20bf215546Sopenharmony_ci *
21bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
28bf215546Sopenharmony_ci */
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include <stdarg.h>
32bf215546Sopenharmony_ci#include <stdio.h>
33bf215546Sopenharmony_ci#include "errors.h"
34bf215546Sopenharmony_ci#include "enums.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "context.h"
37bf215546Sopenharmony_ci#include "debug_output.h"
38bf215546Sopenharmony_ci#include "detect_os.h"
39bf215546Sopenharmony_ci#include "api_exec_decl.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#if DETECT_OS_ANDROID
42bf215546Sopenharmony_ci#  include <log/log.h>
43bf215546Sopenharmony_ci#endif
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_cistatic FILE *LogFile = NULL;
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_cistatic void
49bf215546Sopenharmony_cioutput_if_debug(const char *prefixString, const char *outputString,
50bf215546Sopenharmony_ci                GLboolean newline)
51bf215546Sopenharmony_ci{
52bf215546Sopenharmony_ci   static int debug = -1;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   /* Init the local 'debug' var once.
55bf215546Sopenharmony_ci    * Note: the _mesa_init_debug() function should have been called
56bf215546Sopenharmony_ci    * by now so MESA_DEBUG_FLAGS will be initialized.
57bf215546Sopenharmony_ci    */
58bf215546Sopenharmony_ci   if (debug == -1) {
59bf215546Sopenharmony_ci      /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
60bf215546Sopenharmony_ci       * etc to the named file.  Otherwise, output to stderr.
61bf215546Sopenharmony_ci       */
62bf215546Sopenharmony_ci      const char *logFile = getenv("MESA_LOG_FILE");
63bf215546Sopenharmony_ci      if (logFile)
64bf215546Sopenharmony_ci         LogFile = fopen(logFile, "w");
65bf215546Sopenharmony_ci      if (!LogFile)
66bf215546Sopenharmony_ci         LogFile = stderr;
67bf215546Sopenharmony_ci#ifndef NDEBUG
68bf215546Sopenharmony_ci      /* in debug builds, print messages unless MESA_DEBUG="silent" */
69bf215546Sopenharmony_ci      if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
70bf215546Sopenharmony_ci         debug = 0;
71bf215546Sopenharmony_ci      else
72bf215546Sopenharmony_ci         debug = 1;
73bf215546Sopenharmony_ci#else
74bf215546Sopenharmony_ci      const char *env = getenv("MESA_DEBUG");
75bf215546Sopenharmony_ci      debug = env && strstr(env, "silent") == NULL;
76bf215546Sopenharmony_ci#endif
77bf215546Sopenharmony_ci   }
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   /* Now only print the string if we're required to do so. */
80bf215546Sopenharmony_ci   if (debug) {
81bf215546Sopenharmony_ci      if (prefixString)
82bf215546Sopenharmony_ci         fprintf(LogFile, "%s: %s", prefixString, outputString);
83bf215546Sopenharmony_ci      else
84bf215546Sopenharmony_ci         fprintf(LogFile, "%s", outputString);
85bf215546Sopenharmony_ci      if (newline)
86bf215546Sopenharmony_ci         fprintf(LogFile, "\n");
87bf215546Sopenharmony_ci      fflush(LogFile);
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci#if defined(_WIN32)
90bf215546Sopenharmony_ci      /* stderr from windows applications without console is not usually
91bf215546Sopenharmony_ci       * visible, so communicate with the debugger instead */
92bf215546Sopenharmony_ci      {
93bf215546Sopenharmony_ci         char buf[4096];
94bf215546Sopenharmony_ci         if (prefixString)
95bf215546Sopenharmony_ci            snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
96bf215546Sopenharmony_ci         else
97bf215546Sopenharmony_ci            snprintf(buf, sizeof(buf), "%s%s", outputString, newline ? "\n" : "");
98bf215546Sopenharmony_ci         OutputDebugStringA(buf);
99bf215546Sopenharmony_ci      }
100bf215546Sopenharmony_ci#endif
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci#if DETECT_OS_ANDROID
103bf215546Sopenharmony_ci      LOG_PRI(ANDROID_LOG_ERROR, prefixString ? prefixString : "MESA", "%s%s", outputString, newline ? "\n" : "");
104bf215546Sopenharmony_ci#endif
105bf215546Sopenharmony_ci   }
106bf215546Sopenharmony_ci}
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci/**
110bf215546Sopenharmony_ci * Return the file handle to use for debug/logging.  Defaults to stderr
111bf215546Sopenharmony_ci * unless MESA_LOG_FILE is defined.
112bf215546Sopenharmony_ci */
113bf215546Sopenharmony_ciFILE *
114bf215546Sopenharmony_ci_mesa_get_log_file(void)
115bf215546Sopenharmony_ci{
116bf215546Sopenharmony_ci   assert(LogFile);
117bf215546Sopenharmony_ci   return LogFile;
118bf215546Sopenharmony_ci}
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci/**
122bf215546Sopenharmony_ci * When a new type of error is recorded, print a message describing
123bf215546Sopenharmony_ci * previous errors which were accumulated.
124bf215546Sopenharmony_ci */
125bf215546Sopenharmony_cistatic void
126bf215546Sopenharmony_ciflush_delayed_errors( struct gl_context *ctx )
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   char s[MAX_DEBUG_MESSAGE_LENGTH];
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   if (ctx->ErrorDebugCount) {
131bf215546Sopenharmony_ci      snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors",
132bf215546Sopenharmony_ci                     ctx->ErrorDebugCount,
133bf215546Sopenharmony_ci                     _mesa_enum_to_string(ctx->ErrorValue));
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci      output_if_debug("Mesa", s, GL_TRUE);
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci      ctx->ErrorDebugCount = 0;
138bf215546Sopenharmony_ci   }
139bf215546Sopenharmony_ci}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci/**
143bf215546Sopenharmony_ci * Report a warning (a recoverable error condition) to stderr if
144bf215546Sopenharmony_ci * either DEBUG is defined or the MESA_DEBUG env var is set.
145bf215546Sopenharmony_ci *
146bf215546Sopenharmony_ci * \param ctx GL context.
147bf215546Sopenharmony_ci * \param fmtString printf()-like format string.
148bf215546Sopenharmony_ci */
149bf215546Sopenharmony_civoid
150bf215546Sopenharmony_ci_mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
151bf215546Sopenharmony_ci{
152bf215546Sopenharmony_ci   char str[MAX_DEBUG_MESSAGE_LENGTH];
153bf215546Sopenharmony_ci   va_list args;
154bf215546Sopenharmony_ci   va_start( args, fmtString );
155bf215546Sopenharmony_ci   (void) vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
156bf215546Sopenharmony_ci   va_end( args );
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   if (ctx)
159bf215546Sopenharmony_ci      flush_delayed_errors( ctx );
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   output_if_debug("Mesa warning", str, GL_TRUE);
162bf215546Sopenharmony_ci}
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci/**
166bf215546Sopenharmony_ci * Report an internal implementation problem.
167bf215546Sopenharmony_ci * Prints the message to stderr via fprintf().
168bf215546Sopenharmony_ci *
169bf215546Sopenharmony_ci * \param ctx GL context.
170bf215546Sopenharmony_ci * \param fmtString problem description string.
171bf215546Sopenharmony_ci */
172bf215546Sopenharmony_civoid
173bf215546Sopenharmony_ci_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
174bf215546Sopenharmony_ci{
175bf215546Sopenharmony_ci   va_list args;
176bf215546Sopenharmony_ci   char str[MAX_DEBUG_MESSAGE_LENGTH];
177bf215546Sopenharmony_ci   static int numCalls = 0;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   (void) ctx;
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci   if (numCalls < 50) {
182bf215546Sopenharmony_ci      numCalls++;
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci      va_start( args, fmtString );
185bf215546Sopenharmony_ci      vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
186bf215546Sopenharmony_ci      va_end( args );
187bf215546Sopenharmony_ci      fprintf(stderr, "Mesa " PACKAGE_VERSION " implementation error: %s\n",
188bf215546Sopenharmony_ci              str);
189bf215546Sopenharmony_ci      fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n");
190bf215546Sopenharmony_ci   }
191bf215546Sopenharmony_ci}
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_cistatic GLboolean
195bf215546Sopenharmony_cishould_output(struct gl_context *ctx, GLenum error, const char *fmtString)
196bf215546Sopenharmony_ci{
197bf215546Sopenharmony_ci   static GLint debug = -1;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   /* Check debug environment variable only once:
200bf215546Sopenharmony_ci    */
201bf215546Sopenharmony_ci   if (debug == -1) {
202bf215546Sopenharmony_ci      const char *debugEnv = getenv("MESA_DEBUG");
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci#ifndef NDEBUG
205bf215546Sopenharmony_ci      if (debugEnv && strstr(debugEnv, "silent"))
206bf215546Sopenharmony_ci         debug = GL_FALSE;
207bf215546Sopenharmony_ci      else
208bf215546Sopenharmony_ci         debug = GL_TRUE;
209bf215546Sopenharmony_ci#else
210bf215546Sopenharmony_ci      if (debugEnv)
211bf215546Sopenharmony_ci         debug = GL_TRUE;
212bf215546Sopenharmony_ci      else
213bf215546Sopenharmony_ci         debug = GL_FALSE;
214bf215546Sopenharmony_ci#endif
215bf215546Sopenharmony_ci   }
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci   if (debug) {
218bf215546Sopenharmony_ci      if (ctx->ErrorValue != error ||
219bf215546Sopenharmony_ci          ctx->ErrorDebugFmtString != fmtString) {
220bf215546Sopenharmony_ci         flush_delayed_errors( ctx );
221bf215546Sopenharmony_ci         ctx->ErrorDebugFmtString = fmtString;
222bf215546Sopenharmony_ci         ctx->ErrorDebugCount = 0;
223bf215546Sopenharmony_ci         return GL_TRUE;
224bf215546Sopenharmony_ci      }
225bf215546Sopenharmony_ci      ctx->ErrorDebugCount++;
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci   return GL_FALSE;
228bf215546Sopenharmony_ci}
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_civoid
232bf215546Sopenharmony_ci_mesa_gl_vdebugf(struct gl_context *ctx,
233bf215546Sopenharmony_ci                 GLuint *id,
234bf215546Sopenharmony_ci                 enum mesa_debug_source source,
235bf215546Sopenharmony_ci                 enum mesa_debug_type type,
236bf215546Sopenharmony_ci                 enum mesa_debug_severity severity,
237bf215546Sopenharmony_ci                 const char *fmtString,
238bf215546Sopenharmony_ci                 va_list args)
239bf215546Sopenharmony_ci{
240bf215546Sopenharmony_ci   char s[MAX_DEBUG_MESSAGE_LENGTH];
241bf215546Sopenharmony_ci   int len;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   _mesa_debug_get_id(id);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   len = vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
246bf215546Sopenharmony_ci   if (len >= MAX_DEBUG_MESSAGE_LENGTH)
247bf215546Sopenharmony_ci      /* message was truncated */
248bf215546Sopenharmony_ci      len = MAX_DEBUG_MESSAGE_LENGTH - 1;
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   _mesa_log_msg(ctx, source, type, *id, severity, len, s);
251bf215546Sopenharmony_ci}
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_civoid
255bf215546Sopenharmony_ci_mesa_gl_debugf(struct gl_context *ctx,
256bf215546Sopenharmony_ci                GLuint *id,
257bf215546Sopenharmony_ci                enum mesa_debug_source source,
258bf215546Sopenharmony_ci                enum mesa_debug_type type,
259bf215546Sopenharmony_ci                enum mesa_debug_severity severity,
260bf215546Sopenharmony_ci                const char *fmtString, ...)
261bf215546Sopenharmony_ci{
262bf215546Sopenharmony_ci   va_list args;
263bf215546Sopenharmony_ci   va_start(args, fmtString);
264bf215546Sopenharmony_ci   _mesa_gl_vdebugf(ctx, id, source, type, severity, fmtString, args);
265bf215546Sopenharmony_ci   va_end(args);
266bf215546Sopenharmony_ci}
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_cisize_t
269bf215546Sopenharmony_ci_mesa_gl_debug(struct gl_context *ctx,
270bf215546Sopenharmony_ci               GLuint *id,
271bf215546Sopenharmony_ci               enum mesa_debug_source source,
272bf215546Sopenharmony_ci               enum mesa_debug_type type,
273bf215546Sopenharmony_ci               enum mesa_debug_severity severity,
274bf215546Sopenharmony_ci               const char *msg)
275bf215546Sopenharmony_ci{
276bf215546Sopenharmony_ci   _mesa_debug_get_id(id);
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   size_t len = strnlen(msg, MAX_DEBUG_MESSAGE_LENGTH);
279bf215546Sopenharmony_ci   if (len < MAX_DEBUG_MESSAGE_LENGTH) {
280bf215546Sopenharmony_ci      _mesa_log_msg(ctx, source, type, *id, severity, len, msg);
281bf215546Sopenharmony_ci      return len;
282bf215546Sopenharmony_ci   }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   /* limit the message to fit within KHR_debug buffers */
285bf215546Sopenharmony_ci   char s[MAX_DEBUG_MESSAGE_LENGTH];
286bf215546Sopenharmony_ci   strncpy(s, msg, MAX_DEBUG_MESSAGE_LENGTH);
287bf215546Sopenharmony_ci   s[MAX_DEBUG_MESSAGE_LENGTH - 1] = '\0';
288bf215546Sopenharmony_ci   len = MAX_DEBUG_MESSAGE_LENGTH - 1;
289bf215546Sopenharmony_ci   _mesa_log_msg(ctx, source, type, *id, severity, len, s);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   /* report the number of characters that were logged */
292bf215546Sopenharmony_ci   return len;
293bf215546Sopenharmony_ci}
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci/**
297bf215546Sopenharmony_ci * Record an OpenGL state error.  These usually occur when the user
298bf215546Sopenharmony_ci * passes invalid parameters to a GL function.
299bf215546Sopenharmony_ci *
300bf215546Sopenharmony_ci * If debugging is enabled (either at compile-time via the DEBUG macro, or
301bf215546Sopenharmony_ci * run-time via the MESA_DEBUG environment variable), report the error with
302bf215546Sopenharmony_ci * _mesa_debug().
303bf215546Sopenharmony_ci *
304bf215546Sopenharmony_ci * \param ctx the GL context.
305bf215546Sopenharmony_ci * \param error the error value.
306bf215546Sopenharmony_ci * \param fmtString printf() style format string, followed by optional args
307bf215546Sopenharmony_ci */
308bf215546Sopenharmony_civoid
309bf215546Sopenharmony_ci_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
310bf215546Sopenharmony_ci{
311bf215546Sopenharmony_ci   GLboolean do_output, do_log;
312bf215546Sopenharmony_ci   /* Ideally this would be set up by the caller, so that we had proper IDs
313bf215546Sopenharmony_ci    * per different message.
314bf215546Sopenharmony_ci    */
315bf215546Sopenharmony_ci   static GLuint error_msg_id = 0;
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   _mesa_debug_get_id(&error_msg_id);
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   do_output = should_output(ctx, error, fmtString);
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   simple_mtx_lock(&ctx->DebugMutex);
322bf215546Sopenharmony_ci   if (ctx->Debug) {
323bf215546Sopenharmony_ci      do_log = _mesa_debug_is_message_enabled(ctx->Debug,
324bf215546Sopenharmony_ci                                              MESA_DEBUG_SOURCE_API,
325bf215546Sopenharmony_ci                                              MESA_DEBUG_TYPE_ERROR,
326bf215546Sopenharmony_ci                                              error_msg_id,
327bf215546Sopenharmony_ci                                              MESA_DEBUG_SEVERITY_HIGH);
328bf215546Sopenharmony_ci   }
329bf215546Sopenharmony_ci   else {
330bf215546Sopenharmony_ci      do_log = GL_FALSE;
331bf215546Sopenharmony_ci   }
332bf215546Sopenharmony_ci   simple_mtx_unlock(&ctx->DebugMutex);
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   if (do_output || do_log) {
335bf215546Sopenharmony_ci      char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
336bf215546Sopenharmony_ci      int len;
337bf215546Sopenharmony_ci      va_list args;
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci      va_start(args, fmtString);
340bf215546Sopenharmony_ci      len = vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
341bf215546Sopenharmony_ci      va_end(args);
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
344bf215546Sopenharmony_ci         /* Too long error message. Whoever calls _mesa_error should use
345bf215546Sopenharmony_ci          * shorter strings.
346bf215546Sopenharmony_ci          */
347bf215546Sopenharmony_ci         assert(0);
348bf215546Sopenharmony_ci         return;
349bf215546Sopenharmony_ci      }
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci      len = snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
352bf215546Sopenharmony_ci                           _mesa_enum_to_string(error), s);
353bf215546Sopenharmony_ci      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
354bf215546Sopenharmony_ci         /* Same as above. */
355bf215546Sopenharmony_ci         assert(0);
356bf215546Sopenharmony_ci         return;
357bf215546Sopenharmony_ci      }
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci      /* Print the error to stderr if needed. */
360bf215546Sopenharmony_ci      if (do_output) {
361bf215546Sopenharmony_ci         output_if_debug("Mesa: User error", s2, GL_TRUE);
362bf215546Sopenharmony_ci      }
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci      /* Log the error via ARB_debug_output if needed.*/
365bf215546Sopenharmony_ci      if (do_log) {
366bf215546Sopenharmony_ci         _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR,
367bf215546Sopenharmony_ci                       error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2);
368bf215546Sopenharmony_ci      }
369bf215546Sopenharmony_ci   }
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci   /* Set the GL context error state for glGetError. */
372bf215546Sopenharmony_ci   if (ctx->ErrorValue == GL_NO_ERROR)
373bf215546Sopenharmony_ci      ctx->ErrorValue = error;
374bf215546Sopenharmony_ci}
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_civoid
377bf215546Sopenharmony_ci_mesa_error_no_memory(const char *caller)
378bf215546Sopenharmony_ci{
379bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
380bf215546Sopenharmony_ci   _mesa_error(ctx, GL_OUT_OF_MEMORY, "out of memory in %s", caller);
381bf215546Sopenharmony_ci}
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci/**
384bf215546Sopenharmony_ci * Report debug information.  Print error message to stderr via fprintf().
385bf215546Sopenharmony_ci * No-op if DEBUG mode not enabled.
386bf215546Sopenharmony_ci *
387bf215546Sopenharmony_ci * \param ctx GL context.
388bf215546Sopenharmony_ci * \param fmtString printf()-style format string, followed by optional args.
389bf215546Sopenharmony_ci */
390bf215546Sopenharmony_civoid
391bf215546Sopenharmony_ci_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
392bf215546Sopenharmony_ci{
393bf215546Sopenharmony_ci#ifndef NDEBUG
394bf215546Sopenharmony_ci   char s[MAX_DEBUG_MESSAGE_LENGTH];
395bf215546Sopenharmony_ci   va_list args;
396bf215546Sopenharmony_ci   va_start(args, fmtString);
397bf215546Sopenharmony_ci   vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
398bf215546Sopenharmony_ci   va_end(args);
399bf215546Sopenharmony_ci   output_if_debug("Mesa", s, GL_FALSE);
400bf215546Sopenharmony_ci#endif /* DEBUG */
401bf215546Sopenharmony_ci   (void) ctx;
402bf215546Sopenharmony_ci   (void) fmtString;
403bf215546Sopenharmony_ci}
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_civoid
407bf215546Sopenharmony_ci_mesa_log(const char *fmtString, ...)
408bf215546Sopenharmony_ci{
409bf215546Sopenharmony_ci   char s[MAX_DEBUG_MESSAGE_LENGTH];
410bf215546Sopenharmony_ci   va_list args;
411bf215546Sopenharmony_ci   va_start(args, fmtString);
412bf215546Sopenharmony_ci   vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
413bf215546Sopenharmony_ci   va_end(args);
414bf215546Sopenharmony_ci   output_if_debug(NULL, s, GL_FALSE);
415bf215546Sopenharmony_ci}
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_civoid
418bf215546Sopenharmony_ci_mesa_log_direct(const char *string)
419bf215546Sopenharmony_ci{
420bf215546Sopenharmony_ci   output_if_debug(NULL, string, GL_TRUE);
421bf215546Sopenharmony_ci}
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci/**
424bf215546Sopenharmony_ci * Report debug information from the shader compiler via GL_ARB_debug_output.
425bf215546Sopenharmony_ci *
426bf215546Sopenharmony_ci * \param ctx GL context.
427bf215546Sopenharmony_ci * \param type The namespace to which this message belongs.
428bf215546Sopenharmony_ci * \param id The message ID within the given namespace.
429bf215546Sopenharmony_ci * \param msg The message to output. Must be null-terminated.
430bf215546Sopenharmony_ci */
431bf215546Sopenharmony_civoid
432bf215546Sopenharmony_ci_mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id,
433bf215546Sopenharmony_ci                   const char *msg)
434bf215546Sopenharmony_ci{
435bf215546Sopenharmony_ci   enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
436bf215546Sopenharmony_ci   enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH;
437bf215546Sopenharmony_ci   int len;
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci   _mesa_debug_get_id(id);
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci   len = strlen(msg);
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci   /* Truncate the message if necessary. */
444bf215546Sopenharmony_ci   if (len >= MAX_DEBUG_MESSAGE_LENGTH)
445bf215546Sopenharmony_ci      len = MAX_DEBUG_MESSAGE_LENGTH - 1;
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci   _mesa_log_msg(ctx, source, type, *id, severity, len, msg);
448bf215546Sopenharmony_ci}
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci/**
451bf215546Sopenharmony_ci * Set the parameter as the current GL error. Used by glthread.
452bf215546Sopenharmony_ci */
453bf215546Sopenharmony_civoid GLAPIENTRY
454bf215546Sopenharmony_ci_mesa_InternalSetError(GLenum error)
455bf215546Sopenharmony_ci{
456bf215546Sopenharmony_ci   GET_CURRENT_CONTEXT(ctx);
457bf215546Sopenharmony_ci   _mesa_error(ctx, error, "glthread");
458bf215546Sopenharmony_ci}
459