errors.c revision 622186fbdf47e4c77aadba3e38567636ecbcccf5
1/**
2 * \file errors.c
3 * Mesa debugging and error handling functions.
4 */
5
6/*
7 * Mesa 3-D graphics library
8 *
9 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
10 *
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:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
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.
28 */
29
30
31#include <stdarg.h>
32#include <stdio.h>
33#include "errors.h"
34#include "enums.h"
35#include "imports.h"
36#include "context.h"
37#include "dispatch.h"
38#include "hash.h"
39#include "mtypes.h"
40#include "version.h"
41#include "util/hash_table.h"
42#include "util/simple_list.h"
43
44static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP;
45static GLuint NextDynamicID = 1;
46
47/**
48 * A namespace element.
49 */
50struct gl_debug_element
51{
52   struct simple_node link;
53
54   GLuint ID;
55   /* at which severity levels (mesa_debug_severity) is the message enabled */
56   GLbitfield State;
57};
58
59struct gl_debug_namespace
60{
61   struct simple_node Elements;
62   GLbitfield DefaultState;
63};
64
65struct gl_debug_group {
66   struct gl_debug_namespace Namespaces[MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
67};
68
69/**
70 * An error, warning, or other piece of debug information for an application
71 * to consume via GL_ARB_debug_output/GL_KHR_debug.
72 */
73struct gl_debug_message
74{
75   enum mesa_debug_source source;
76   enum mesa_debug_type type;
77   GLuint id;
78   enum mesa_debug_severity severity;
79   GLsizei length;
80   GLcharARB *message;
81};
82
83/**
84 * Debug message log.  It works like a ring buffer.
85 */
86struct gl_debug_log {
87   struct gl_debug_message Messages[MAX_DEBUG_LOGGED_MESSAGES];
88   GLint NextMessage;
89   GLint NumMessages;
90};
91
92struct gl_debug_state
93{
94   GLDEBUGPROC Callback;
95   const void *CallbackData;
96   GLboolean SyncOutput;
97   GLboolean DebugOutput;
98
99   struct gl_debug_group *Groups[MAX_DEBUG_GROUP_STACK_DEPTH];
100   struct gl_debug_message GroupMessages[MAX_DEBUG_GROUP_STACK_DEPTH];
101   GLint CurrentGroup; // GroupStackDepth - 1
102
103   struct gl_debug_log Log;
104};
105
106static char out_of_memory[] = "Debugging error: out of memory";
107
108static const GLenum debug_source_enums[] = {
109   GL_DEBUG_SOURCE_API,
110   GL_DEBUG_SOURCE_WINDOW_SYSTEM,
111   GL_DEBUG_SOURCE_SHADER_COMPILER,
112   GL_DEBUG_SOURCE_THIRD_PARTY,
113   GL_DEBUG_SOURCE_APPLICATION,
114   GL_DEBUG_SOURCE_OTHER,
115};
116
117static const GLenum debug_type_enums[] = {
118   GL_DEBUG_TYPE_ERROR,
119   GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
120   GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
121   GL_DEBUG_TYPE_PORTABILITY,
122   GL_DEBUG_TYPE_PERFORMANCE,
123   GL_DEBUG_TYPE_OTHER,
124   GL_DEBUG_TYPE_MARKER,
125   GL_DEBUG_TYPE_PUSH_GROUP,
126   GL_DEBUG_TYPE_POP_GROUP,
127};
128
129static const GLenum debug_severity_enums[] = {
130   GL_DEBUG_SEVERITY_LOW,
131   GL_DEBUG_SEVERITY_MEDIUM,
132   GL_DEBUG_SEVERITY_HIGH,
133   GL_DEBUG_SEVERITY_NOTIFICATION,
134};
135
136
137static enum mesa_debug_source
138gl_enum_to_debug_source(GLenum e)
139{
140   unsigned i;
141
142   for (i = 0; i < ARRAY_SIZE(debug_source_enums); i++) {
143      if (debug_source_enums[i] == e)
144         break;
145   }
146   return i;
147}
148
149static enum mesa_debug_type
150gl_enum_to_debug_type(GLenum e)
151{
152   unsigned i;
153
154   for (i = 0; i < ARRAY_SIZE(debug_type_enums); i++) {
155      if (debug_type_enums[i] == e)
156         break;
157   }
158   return i;
159}
160
161static enum mesa_debug_severity
162gl_enum_to_debug_severity(GLenum e)
163{
164   unsigned i;
165
166   for (i = 0; i < ARRAY_SIZE(debug_severity_enums); i++) {
167      if (debug_severity_enums[i] == e)
168         break;
169   }
170   return i;
171}
172
173
174/**
175 * Handles generating a GL_ARB_debug_output message ID generated by the GL or
176 * GLSL compiler.
177 *
178 * The GL API has this "ID" mechanism, where the intention is to allow a
179 * client to filter in/out messages based on source, type, and ID.  Of course,
180 * building a giant enum list of all debug output messages that Mesa might
181 * generate is ridiculous, so instead we have our caller pass us a pointer to
182 * static storage where the ID should get stored.  This ID will be shared
183 * across all contexts for that message (which seems like a desirable
184 * property, even if it's not expected by the spec), but note that it won't be
185 * the same between executions if messages aren't generated in the same order.
186 */
187static void
188debug_get_id(GLuint *id)
189{
190   if (!(*id)) {
191      mtx_lock(&DynamicIDMutex);
192      if (!(*id))
193         *id = NextDynamicID++;
194      mtx_unlock(&DynamicIDMutex);
195   }
196}
197
198static void
199debug_message_clear(struct gl_debug_message *msg)
200{
201   if (msg->message != (char*)out_of_memory)
202      free(msg->message);
203   msg->message = NULL;
204   msg->length = 0;
205}
206
207static void
208debug_message_store(struct gl_debug_message *msg,
209                    enum mesa_debug_source source,
210                    enum mesa_debug_type type, GLuint id,
211                    enum mesa_debug_severity severity,
212                    GLsizei len, const char *buf)
213{
214   assert(!msg->message && !msg->length);
215
216   msg->message = malloc(len+1);
217   if (msg->message) {
218      (void) strncpy(msg->message, buf, (size_t)len);
219      msg->message[len] = '\0';
220
221      msg->length = len+1;
222      msg->source = source;
223      msg->type = type;
224      msg->id = id;
225      msg->severity = severity;
226   } else {
227      static GLuint oom_msg_id = 0;
228      debug_get_id(&oom_msg_id);
229
230      /* malloc failed! */
231      msg->message = out_of_memory;
232      msg->length = strlen(out_of_memory)+1;
233      msg->source = MESA_DEBUG_SOURCE_OTHER;
234      msg->type = MESA_DEBUG_TYPE_ERROR;
235      msg->id = oom_msg_id;
236      msg->severity = MESA_DEBUG_SEVERITY_HIGH;
237   }
238}
239
240static void
241debug_namespace_init(struct gl_debug_namespace *ns)
242{
243   make_empty_list(&ns->Elements);
244
245   /* Enable all the messages with severity HIGH or MEDIUM by default */
246   ns->DefaultState = (1 << MESA_DEBUG_SEVERITY_MEDIUM ) |
247                      (1 << MESA_DEBUG_SEVERITY_HIGH) |
248                      (1 << MESA_DEBUG_SEVERITY_NOTIFICATION);
249}
250
251static void
252debug_namespace_clear(struct gl_debug_namespace *ns)
253{
254   struct simple_node *node, *tmp;
255
256   foreach_s(node, tmp, &ns->Elements)
257      free(node);
258}
259
260static bool
261debug_namespace_copy(struct gl_debug_namespace *dst,
262                     const struct gl_debug_namespace *src)
263{
264   struct simple_node *node;
265
266   dst->DefaultState = src->DefaultState;
267
268   make_empty_list(&dst->Elements);
269   foreach(node, &src->Elements) {
270      const struct gl_debug_element *elem =
271         (const struct gl_debug_element *) node;
272      struct gl_debug_element *copy;
273
274      copy = malloc(sizeof(*copy));
275      if (!copy) {
276         debug_namespace_clear(dst);
277         return false;
278      }
279
280      copy->ID = elem->ID;
281      copy->State = elem->State;
282      insert_at_tail(&dst->Elements, &copy->link);
283   }
284
285   return true;
286}
287
288/**
289 * Set the state of \p id in the namespace.
290 */
291static bool
292debug_namespace_set(struct gl_debug_namespace *ns,
293                    GLuint id, bool enabled)
294{
295   const uint32_t state = (enabled) ?
296      ((1 << MESA_DEBUG_SEVERITY_COUNT) - 1) : 0;
297   struct gl_debug_element *elem = NULL;
298   struct simple_node *node;
299
300   /* find the element */
301   foreach(node, &ns->Elements) {
302      struct gl_debug_element *tmp = (struct gl_debug_element *) node;
303      if (tmp->ID == id) {
304         elem = tmp;
305         break;
306      }
307   }
308
309   /* we do not need the element if it has the default state */
310   if (ns->DefaultState == state) {
311      if (elem) {
312         remove_from_list(&elem->link);
313         free(elem);
314      }
315      return true;
316   }
317
318   if (!elem) {
319      elem = malloc(sizeof(*elem));
320      if (!elem)
321         return false;
322
323      elem->ID = id;
324      insert_at_tail(&ns->Elements, &elem->link);
325   }
326
327   elem->State = state;
328
329   return true;
330}
331
332/**
333 * Set the default state of the namespace for \p severity.  When \p severity
334 * is MESA_DEBUG_SEVERITY_COUNT, the default values for all severities are
335 * updated.
336 */
337static void
338debug_namespace_set_all(struct gl_debug_namespace *ns,
339                        enum mesa_debug_severity severity,
340                        bool enabled)
341{
342   struct simple_node *node, *tmp;
343   uint32_t mask, val;
344
345   /* set all elements to the same state */
346   if (severity == MESA_DEBUG_SEVERITY_COUNT) {
347      ns->DefaultState = (enabled) ? ((1 << severity) - 1) : 0;
348      debug_namespace_clear(ns);
349      make_empty_list(&ns->Elements);
350      return;
351   }
352
353   mask = 1 << severity;
354   val = (enabled) ? mask : 0;
355
356   ns->DefaultState = (ns->DefaultState & ~mask) | val;
357
358   foreach_s(node, tmp, &ns->Elements) {
359      struct gl_debug_element *elem = (struct gl_debug_element *) node;
360
361      elem->State = (elem->State & ~mask) | val;
362      if (elem->State == ns->DefaultState) {
363         remove_from_list(node);
364         free(node);
365      }
366   }
367}
368
369/**
370 * Get the state of \p id in the namespace.
371 */
372static bool
373debug_namespace_get(const struct gl_debug_namespace *ns, GLuint id,
374                    enum mesa_debug_severity severity)
375{
376   struct simple_node *node;
377   uint32_t state;
378
379   state = ns->DefaultState;
380   foreach(node, &ns->Elements) {
381      struct gl_debug_element *elem = (struct gl_debug_element *) node;
382
383      if (elem->ID == id) {
384         state = elem->State;
385         break;
386      }
387   }
388
389   return (state & (1 << severity));
390}
391
392/**
393 * Allocate and initialize context debug state.
394 */
395static struct gl_debug_state *
396debug_create(void)
397{
398   struct gl_debug_state *debug;
399   int s, t;
400
401   debug = CALLOC_STRUCT(gl_debug_state);
402   if (!debug)
403      return NULL;
404
405   debug->Groups[0] = malloc(sizeof(*debug->Groups[0]));
406   if (!debug->Groups[0]) {
407      free(debug);
408      return NULL;
409   }
410
411   /* Initialize state for filtering known debug messages. */
412   for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
413      for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
414         debug_namespace_init(&debug->Groups[0]->Namespaces[s][t]);
415   }
416
417   return debug;
418}
419
420/**
421 * Return true if the top debug group points to the group below it.
422 */
423static bool
424debug_is_group_read_only(const struct gl_debug_state *debug)
425{
426   const GLint gstack = debug->CurrentGroup;
427   return (gstack > 0 && debug->Groups[gstack] == debug->Groups[gstack - 1]);
428}
429
430/**
431 * Make the top debug group writable.
432 */
433static bool
434debug_make_group_writable(struct gl_debug_state *debug)
435{
436   const GLint gstack = debug->CurrentGroup;
437   const struct gl_debug_group *src = debug->Groups[gstack];
438   struct gl_debug_group *dst;
439   int s, t;
440
441   if (!debug_is_group_read_only(debug))
442      return true;
443
444   dst = malloc(sizeof(*dst));
445   if (!dst)
446      return false;
447
448   for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
449      for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
450         if (!debug_namespace_copy(&dst->Namespaces[s][t],
451                                   &src->Namespaces[s][t])) {
452            /* error path! */
453            for (t = t - 1; t >= 0; t--)
454               debug_namespace_clear(&dst->Namespaces[s][t]);
455            for (s = s - 1; s >= 0; s--) {
456               for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
457                  debug_namespace_clear(&dst->Namespaces[s][t]);
458            }
459            free(dst);
460            return false;
461         }
462      }
463   }
464
465   debug->Groups[gstack] = dst;
466
467   return true;
468}
469
470/**
471 * Free the top debug group.
472 */
473static void
474debug_clear_group(struct gl_debug_state *debug)
475{
476   const GLint gstack = debug->CurrentGroup;
477
478   if (!debug_is_group_read_only(debug)) {
479      struct gl_debug_group *grp = debug->Groups[gstack];
480      int s, t;
481
482      for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
483         for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
484            debug_namespace_clear(&grp->Namespaces[s][t]);
485      }
486
487      free(grp);
488   }
489
490   debug->Groups[gstack] = NULL;
491}
492
493/**
494 * Loop through debug group stack tearing down states for
495 * filtering debug messages.  Then free debug output state.
496 */
497static void
498debug_destroy(struct gl_debug_state *debug)
499{
500   while (debug->CurrentGroup > 0) {
501      debug_clear_group(debug);
502      debug->CurrentGroup--;
503   }
504
505   debug_clear_group(debug);
506   free(debug);
507}
508
509/**
510 * Sets the state of the given message source/type/ID tuple.
511 */
512static void
513debug_set_message_enable(struct gl_debug_state *debug,
514                         enum mesa_debug_source source,
515                         enum mesa_debug_type type,
516                         GLuint id, GLboolean enabled)
517{
518   const GLint gstack = debug->CurrentGroup;
519   struct gl_debug_namespace *ns;
520
521   debug_make_group_writable(debug);
522   ns = &debug->Groups[gstack]->Namespaces[source][type];
523
524   debug_namespace_set(ns, id, enabled);
525}
526
527/*
528 * Set the state of all message IDs found in the given intersection of
529 * 'source', 'type', and 'severity'.  The _COUNT enum can be used for
530 * GL_DONT_CARE (include all messages in the class).
531 *
532 * This requires both setting the state of all previously seen message
533 * IDs in the hash table, and setting the default state for all
534 * applicable combinations of source/type/severity, so that all the
535 * yet-unknown message IDs that may be used in the future will be
536 * impacted as if they were already known.
537 */
538static void
539debug_set_message_enable_all(struct gl_debug_state *debug,
540                             enum mesa_debug_source source,
541                             enum mesa_debug_type type,
542                             enum mesa_debug_severity severity,
543                             GLboolean enabled)
544{
545   const GLint gstack = debug->CurrentGroup;
546   int s, t, smax, tmax;
547
548   if (source == MESA_DEBUG_SOURCE_COUNT) {
549      source = 0;
550      smax = MESA_DEBUG_SOURCE_COUNT;
551   } else {
552      smax = source+1;
553   }
554
555   if (type == MESA_DEBUG_TYPE_COUNT) {
556      type = 0;
557      tmax = MESA_DEBUG_TYPE_COUNT;
558   } else {
559      tmax = type+1;
560   }
561
562   debug_make_group_writable(debug);
563
564   for (s = source; s < smax; s++) {
565      for (t = type; t < tmax; t++) {
566         struct gl_debug_namespace *nspace =
567            &debug->Groups[gstack]->Namespaces[s][t];
568         debug_namespace_set_all(nspace, severity, enabled);
569      }
570   }
571}
572
573/**
574 * Returns if the given message source/type/ID tuple is enabled.
575 */
576static bool
577debug_is_message_enabled(const struct gl_debug_state *debug,
578                         enum mesa_debug_source source,
579                         enum mesa_debug_type type,
580                         GLuint id,
581                         enum mesa_debug_severity severity)
582{
583   const GLint gstack = debug->CurrentGroup;
584   struct gl_debug_group *grp = debug->Groups[gstack];
585   struct gl_debug_namespace *nspace = &grp->Namespaces[source][type];
586
587   if (!debug->DebugOutput)
588      return false;
589
590   return debug_namespace_get(nspace, id, severity);
591}
592
593/**
594 * 'buf' is not necessarily a null-terminated string. When logging, copy
595 * 'len' characters from it, store them in a new, null-terminated string,
596 * and remember the number of bytes used by that string, *including*
597 * the null terminator this time.
598 */
599static void
600debug_log_message(struct gl_debug_state *debug,
601                  enum mesa_debug_source source,
602                  enum mesa_debug_type type, GLuint id,
603                  enum mesa_debug_severity severity,
604                  GLsizei len, const char *buf)
605{
606   struct gl_debug_log *log = &debug->Log;
607   GLint nextEmpty;
608   struct gl_debug_message *emptySlot;
609
610   assert(len >= 0 && len < MAX_DEBUG_MESSAGE_LENGTH);
611
612   if (log->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
613      return;
614
615   nextEmpty = (log->NextMessage + log->NumMessages)
616      % MAX_DEBUG_LOGGED_MESSAGES;
617   emptySlot = &log->Messages[nextEmpty];
618
619   debug_message_store(emptySlot, source, type,
620                       id, severity, len, buf);
621
622   log->NumMessages++;
623}
624
625/**
626 * Return the oldest debug message out of the log.
627 */
628static const struct gl_debug_message *
629debug_fetch_message(const struct gl_debug_state *debug)
630{
631   const struct gl_debug_log *log = &debug->Log;
632
633   return (log->NumMessages) ? &log->Messages[log->NextMessage] : NULL;
634}
635
636/**
637 * Delete the oldest debug messages out of the log.
638 */
639static void
640debug_delete_messages(struct gl_debug_state *debug, int count)
641{
642   struct gl_debug_log *log = &debug->Log;
643
644   if (count > log->NumMessages)
645      count = log->NumMessages;
646
647   while (count--) {
648      struct gl_debug_message *msg = &log->Messages[log->NextMessage];
649
650      debug_message_clear(msg);
651
652      log->NumMessages--;
653      log->NextMessage++;
654      log->NextMessage %= MAX_DEBUG_LOGGED_MESSAGES;
655   }
656}
657
658static struct gl_debug_message *
659debug_get_group_message(struct gl_debug_state *debug)
660{
661   return &debug->GroupMessages[debug->CurrentGroup];
662}
663
664static void
665debug_push_group(struct gl_debug_state *debug)
666{
667   const GLint gstack = debug->CurrentGroup;
668
669   /* just point to the previous stack */
670   debug->Groups[gstack + 1] = debug->Groups[gstack];
671   debug->CurrentGroup++;
672}
673
674static void
675debug_pop_group(struct gl_debug_state *debug)
676{
677   debug_clear_group(debug);
678   debug->CurrentGroup--;
679}
680
681
682/**
683 * Lock and return debug state for the context.  The debug state will be
684 * allocated and initialized upon the first call.  When NULL is returned, the
685 * debug state is not locked.
686 */
687static struct gl_debug_state *
688_mesa_lock_debug_state(struct gl_context *ctx)
689{
690   mtx_lock(&ctx->DebugMutex);
691
692   if (!ctx->Debug) {
693      ctx->Debug = debug_create();
694      if (!ctx->Debug) {
695         GET_CURRENT_CONTEXT(cur);
696         mtx_unlock(&ctx->DebugMutex);
697
698         /*
699          * This function may be called from other threads.  When that is the
700          * case, we cannot record this OOM error.
701          */
702         if (ctx == cur)
703            _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
704
705         return NULL;
706      }
707   }
708
709   return ctx->Debug;
710}
711
712static void
713_mesa_unlock_debug_state(struct gl_context *ctx)
714{
715   mtx_unlock(&ctx->DebugMutex);
716}
717
718/**
719 * Set the integer debug state specified by \p pname.  This can be called from
720 * _mesa_set_enable for example.
721 */
722bool
723_mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val)
724{
725   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
726
727   if (!debug)
728      return false;
729
730   switch (pname) {
731   case GL_DEBUG_OUTPUT:
732      debug->DebugOutput = (val != 0);
733      break;
734   case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
735      debug->SyncOutput = (val != 0);
736      break;
737   default:
738      assert(!"unknown debug output param");
739      break;
740   }
741
742   _mesa_unlock_debug_state(ctx);
743
744   return true;
745}
746
747/**
748 * Query the integer debug state specified by \p pname.  This can be called
749 * _mesa_GetIntegerv for example.
750 */
751GLint
752_mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
753{
754   struct gl_debug_state *debug;
755   GLint val;
756
757   mtx_lock(&ctx->DebugMutex);
758   debug = ctx->Debug;
759   if (!debug) {
760      mtx_unlock(&ctx->DebugMutex);
761      return 0;
762   }
763
764   switch (pname) {
765   case GL_DEBUG_OUTPUT:
766      val = debug->DebugOutput;
767      break;
768   case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
769      val = debug->SyncOutput;
770      break;
771   case GL_DEBUG_LOGGED_MESSAGES:
772      val = debug->Log.NumMessages;
773      break;
774   case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
775      val = (debug->Log.NumMessages) ?
776         debug->Log.Messages[debug->Log.NextMessage].length : 0;
777      break;
778   case GL_DEBUG_GROUP_STACK_DEPTH:
779      val = debug->CurrentGroup + 1;
780      break;
781   default:
782      assert(!"unknown debug output param");
783      val = 0;
784      break;
785   }
786
787   mtx_unlock(&ctx->DebugMutex);
788
789   return val;
790}
791
792/**
793 * Query the pointer debug state specified by \p pname.  This can be called
794 * _mesa_GetPointerv for example.
795 */
796void *
797_mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname)
798{
799   struct gl_debug_state *debug;
800   void *val;
801
802   mtx_lock(&ctx->DebugMutex);
803   debug = ctx->Debug;
804   if (!debug) {
805      mtx_unlock(&ctx->DebugMutex);
806      return NULL;
807   }
808
809   switch (pname) {
810   case GL_DEBUG_CALLBACK_FUNCTION_ARB:
811      val = (void *) debug->Callback;
812      break;
813   case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
814      val = (void *) debug->CallbackData;
815      break;
816   default:
817      assert(!"unknown debug output param");
818      val = NULL;
819      break;
820   }
821
822   mtx_unlock(&ctx->DebugMutex);
823
824   return val;
825}
826
827/**
828 * Insert a debug message.  The mutex is assumed to be locked, and will be
829 * unlocked by this call.
830 */
831static void
832log_msg_locked_and_unlock(struct gl_context *ctx,
833                          enum mesa_debug_source source,
834                          enum mesa_debug_type type, GLuint id,
835                          enum mesa_debug_severity severity,
836                          GLint len, const char *buf)
837{
838   struct gl_debug_state *debug = ctx->Debug;
839
840   if (!debug_is_message_enabled(debug, source, type, id, severity)) {
841      _mesa_unlock_debug_state(ctx);
842      return;
843   }
844
845   if (ctx->Debug->Callback) {
846      GLenum gl_source = debug_source_enums[source];
847      GLenum gl_type = debug_type_enums[type];
848      GLenum gl_severity = debug_severity_enums[severity];
849      GLDEBUGPROC callback = ctx->Debug->Callback;
850      const void *data = ctx->Debug->CallbackData;
851
852      /*
853       * When ctx->Debug->SyncOutput is GL_FALSE, the client is prepared for
854       * unsynchronous calls.  When it is GL_TRUE, we will not spawn threads.
855       * In either case, we can call the callback unlocked.
856       */
857      _mesa_unlock_debug_state(ctx);
858      callback(gl_source, gl_type, id, gl_severity, len, buf, data);
859   }
860   else {
861      debug_log_message(ctx->Debug, source, type, id, severity, len, buf);
862      _mesa_unlock_debug_state(ctx);
863   }
864}
865
866/**
867 * Log a client or driver debug message.
868 */
869static void
870log_msg(struct gl_context *ctx, enum mesa_debug_source source,
871        enum mesa_debug_type type, GLuint id,
872        enum mesa_debug_severity severity, GLint len, const char *buf)
873{
874   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
875
876   if (!debug)
877      return;
878
879   log_msg_locked_and_unlock(ctx, source, type, id, severity, len, buf);
880}
881
882
883/**
884 * Verify that source, type, and severity are valid enums.
885 *
886 * The 'caller' param is used for handling values available
887 * only in glDebugMessageInsert or glDebugMessageControl
888 */
889static GLboolean
890validate_params(struct gl_context *ctx, unsigned caller,
891                const char *callerstr, GLenum source, GLenum type,
892                GLenum severity)
893{
894#define INSERT 1
895#define CONTROL 2
896   switch(source) {
897   case GL_DEBUG_SOURCE_APPLICATION_ARB:
898   case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
899      break;
900   case GL_DEBUG_SOURCE_API_ARB:
901   case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
902   case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
903   case GL_DEBUG_SOURCE_OTHER_ARB:
904      if (caller != INSERT)
905         break;
906      else
907         goto error;
908   case GL_DONT_CARE:
909      if (caller == CONTROL)
910         break;
911      else
912         goto error;
913   default:
914      goto error;
915   }
916
917   switch(type) {
918   case GL_DEBUG_TYPE_ERROR_ARB:
919   case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
920   case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
921   case GL_DEBUG_TYPE_PERFORMANCE_ARB:
922   case GL_DEBUG_TYPE_PORTABILITY_ARB:
923   case GL_DEBUG_TYPE_OTHER_ARB:
924   case GL_DEBUG_TYPE_MARKER:
925   case GL_DEBUG_TYPE_PUSH_GROUP:
926   case GL_DEBUG_TYPE_POP_GROUP:
927      break;
928   case GL_DONT_CARE:
929      if (caller == CONTROL)
930         break;
931      else
932         goto error;
933   default:
934      goto error;
935   }
936
937   switch(severity) {
938   case GL_DEBUG_SEVERITY_HIGH_ARB:
939   case GL_DEBUG_SEVERITY_MEDIUM_ARB:
940   case GL_DEBUG_SEVERITY_LOW_ARB:
941   case GL_DEBUG_SEVERITY_NOTIFICATION:
942      break;
943   case GL_DONT_CARE:
944      if (caller == CONTROL)
945         break;
946      else
947         goto error;
948   default:
949      goto error;
950   }
951   return GL_TRUE;
952
953error:
954   _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s"
955               "(source=0x%x, type=0x%x, severity=0x%x)", callerstr,
956               source, type, severity);
957
958   return GL_FALSE;
959}
960
961
962static GLboolean
963validate_length(struct gl_context *ctx, const char *callerstr, GLsizei length,
964                const GLchar *buf)
965{
966
967   if (length < 0) {
968      GLsizei len = strlen(buf);
969
970      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
971         _mesa_error(ctx, GL_INVALID_VALUE,
972                    "%s(null terminated string length=%d, is not less than "
973                    "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, len,
974                    MAX_DEBUG_MESSAGE_LENGTH);
975         return GL_FALSE;
976      }
977   }
978
979   if (length >= MAX_DEBUG_MESSAGE_LENGTH) {
980      _mesa_error(ctx, GL_INVALID_VALUE,
981                 "%s(length=%d, which is not less than "
982                 "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, length,
983                 MAX_DEBUG_MESSAGE_LENGTH);
984      return GL_FALSE;
985   }
986
987   return GL_TRUE;
988}
989
990
991void GLAPIENTRY
992_mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
993                         GLenum severity, GLint length,
994                         const GLchar *buf)
995{
996   GET_CURRENT_CONTEXT(ctx);
997   const char *callerstr;
998
999   if (_mesa_is_desktop_gl(ctx))
1000      callerstr = "glDebugMessageInsert";
1001   else
1002      callerstr = "glDebugMessageInsertKHR";
1003
1004   if (!validate_params(ctx, INSERT, callerstr, source, type, severity))
1005      return; /* GL_INVALID_ENUM */
1006
1007   if (length < 0)
1008      length = strlen(buf);
1009   if (!validate_length(ctx, callerstr, length, buf))
1010      return; /* GL_INVALID_VALUE */
1011
1012   log_msg(ctx, gl_enum_to_debug_source(source),
1013           gl_enum_to_debug_type(type), id,
1014           gl_enum_to_debug_severity(severity),
1015           length, buf);
1016}
1017
1018
1019GLuint GLAPIENTRY
1020_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
1021                         GLenum *types, GLenum *ids, GLenum *severities,
1022                         GLsizei *lengths, GLchar *messageLog)
1023{
1024   GET_CURRENT_CONTEXT(ctx);
1025   struct gl_debug_state *debug;
1026   const char *callerstr;
1027   GLuint ret;
1028
1029   if (_mesa_is_desktop_gl(ctx))
1030      callerstr = "glGetDebugMessageLog";
1031   else
1032      callerstr = "glGetDebugMessageLogKHR";
1033
1034   if (!messageLog)
1035      logSize = 0;
1036
1037   if (logSize < 0) {
1038      _mesa_error(ctx, GL_INVALID_VALUE,
1039                  "%s(logSize=%d : logSize must not be negative)",
1040                  callerstr, logSize);
1041      return 0;
1042   }
1043
1044   debug = _mesa_lock_debug_state(ctx);
1045   if (!debug)
1046      return 0;
1047
1048   for (ret = 0; ret < count; ret++) {
1049      const struct gl_debug_message *msg = debug_fetch_message(debug);
1050
1051      if (!msg)
1052         break;
1053
1054      if (logSize < msg->length && messageLog != NULL)
1055         break;
1056
1057      if (messageLog) {
1058         assert(msg->message[msg->length-1] == '\0');
1059         (void) strncpy(messageLog, msg->message, (size_t)msg->length);
1060
1061         messageLog += msg->length;
1062         logSize -= msg->length;
1063      }
1064
1065      if (lengths)
1066         *lengths++ = msg->length;
1067      if (severities)
1068         *severities++ = debug_severity_enums[msg->severity];
1069      if (sources)
1070         *sources++ = debug_source_enums[msg->source];
1071      if (types)
1072         *types++ = debug_type_enums[msg->type];
1073      if (ids)
1074         *ids++ = msg->id;
1075
1076      debug_delete_messages(debug, 1);
1077   }
1078
1079   _mesa_unlock_debug_state(ctx);
1080
1081   return ret;
1082}
1083
1084
1085void GLAPIENTRY
1086_mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
1087                          GLenum gl_severity, GLsizei count,
1088                          const GLuint *ids, GLboolean enabled)
1089{
1090   GET_CURRENT_CONTEXT(ctx);
1091   enum mesa_debug_source source = gl_enum_to_debug_source(gl_source);
1092   enum mesa_debug_type type = gl_enum_to_debug_type(gl_type);
1093   enum mesa_debug_severity severity = gl_enum_to_debug_severity(gl_severity);
1094   const char *callerstr;
1095   struct gl_debug_state *debug;
1096
1097   if (_mesa_is_desktop_gl(ctx))
1098      callerstr = "glDebugMessageControl";
1099   else
1100      callerstr = "glDebugMessageControlKHR";
1101
1102   if (count < 0) {
1103      _mesa_error(ctx, GL_INVALID_VALUE,
1104                  "%s(count=%d : count must not be negative)", callerstr,
1105                  count);
1106      return;
1107   }
1108
1109   if (!validate_params(ctx, CONTROL, callerstr, gl_source, gl_type,
1110                        gl_severity))
1111      return; /* GL_INVALID_ENUM */
1112
1113   if (count && (gl_severity != GL_DONT_CARE || gl_type == GL_DONT_CARE
1114                 || gl_source == GL_DONT_CARE)) {
1115      _mesa_error(ctx, GL_INVALID_OPERATION,
1116                  "%s(When passing an array of ids, severity must be"
1117         " GL_DONT_CARE, and source and type must not be GL_DONT_CARE.",
1118                  callerstr);
1119      return;
1120   }
1121
1122   debug = _mesa_lock_debug_state(ctx);
1123   if (!debug)
1124      return;
1125
1126   if (count) {
1127      GLsizei i;
1128      for (i = 0; i < count; i++)
1129         debug_set_message_enable(debug, source, type, ids[i], enabled);
1130   }
1131   else {
1132      debug_set_message_enable_all(debug, source, type, severity, enabled);
1133   }
1134
1135   _mesa_unlock_debug_state(ctx);
1136}
1137
1138
1139void GLAPIENTRY
1140_mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam)
1141{
1142   GET_CURRENT_CONTEXT(ctx);
1143   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
1144   if (debug) {
1145      debug->Callback = callback;
1146      debug->CallbackData = userParam;
1147      _mesa_unlock_debug_state(ctx);
1148   }
1149}
1150
1151
1152void GLAPIENTRY
1153_mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
1154                     const GLchar *message)
1155{
1156   GET_CURRENT_CONTEXT(ctx);
1157   const char *callerstr;
1158   struct gl_debug_state *debug;
1159   struct gl_debug_message *emptySlot;
1160
1161   if (_mesa_is_desktop_gl(ctx))
1162      callerstr = "glPushDebugGroup";
1163   else
1164      callerstr = "glPushDebugGroupKHR";
1165
1166   switch(source) {
1167   case GL_DEBUG_SOURCE_APPLICATION:
1168   case GL_DEBUG_SOURCE_THIRD_PARTY:
1169      break;
1170   default:
1171      _mesa_error(ctx, GL_INVALID_ENUM, "bad value passed to %s"
1172                  "(source=0x%x)", callerstr, source);
1173      return;
1174   }
1175
1176   if (length < 0)
1177      length = strlen(message);
1178   if (!validate_length(ctx, callerstr, length, message))
1179      return; /* GL_INVALID_VALUE */
1180
1181   debug = _mesa_lock_debug_state(ctx);
1182   if (!debug)
1183      return;
1184
1185   if (debug->CurrentGroup >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
1186      _mesa_unlock_debug_state(ctx);
1187      _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
1188      return;
1189   }
1190
1191   /* pop reuses the message details from push so we store this */
1192   emptySlot = debug_get_group_message(debug);
1193   debug_message_store(emptySlot,
1194                       gl_enum_to_debug_source(source),
1195                       gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP),
1196                       id,
1197                       gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
1198                       length, message);
1199
1200   debug_push_group(debug);
1201
1202   log_msg_locked_and_unlock(ctx,
1203         gl_enum_to_debug_source(source),
1204         MESA_DEBUG_TYPE_PUSH_GROUP, id,
1205         MESA_DEBUG_SEVERITY_NOTIFICATION, length,
1206         message);
1207}
1208
1209
1210void GLAPIENTRY
1211_mesa_PopDebugGroup(void)
1212{
1213   GET_CURRENT_CONTEXT(ctx);
1214   const char *callerstr;
1215   struct gl_debug_state *debug;
1216   struct gl_debug_message *gdmessage, msg;
1217
1218   if (_mesa_is_desktop_gl(ctx))
1219      callerstr = "glPopDebugGroup";
1220   else
1221      callerstr = "glPopDebugGroupKHR";
1222
1223   debug = _mesa_lock_debug_state(ctx);
1224   if (!debug)
1225      return;
1226
1227   if (debug->CurrentGroup <= 0) {
1228      _mesa_unlock_debug_state(ctx);
1229      _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr);
1230      return;
1231   }
1232
1233   debug_pop_group(debug);
1234
1235   /* make a shallow copy */
1236   gdmessage = debug_get_group_message(debug);
1237   msg = *gdmessage;
1238   gdmessage->message = NULL;
1239   gdmessage->length = 0;
1240
1241   log_msg_locked_and_unlock(ctx,
1242         msg.source,
1243         gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP),
1244         msg.id,
1245         gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
1246         msg.length, msg.message);
1247
1248   debug_message_clear(&msg);
1249}
1250
1251
1252void
1253_mesa_init_errors(struct gl_context *ctx)
1254{
1255   mtx_init(&ctx->DebugMutex, mtx_plain);
1256}
1257
1258
1259void
1260_mesa_free_errors_data(struct gl_context *ctx)
1261{
1262   if (ctx->Debug) {
1263      debug_destroy(ctx->Debug);
1264      /* set to NULL just in case it is used before context is completely gone. */
1265      ctx->Debug = NULL;
1266   }
1267
1268   mtx_destroy(&ctx->DebugMutex);
1269}
1270
1271
1272/**********************************************************************/
1273/** \name Diagnostics */
1274/*@{*/
1275
1276static FILE *LogFile = NULL;
1277
1278
1279static void
1280output_if_debug(const char *prefixString, const char *outputString,
1281                GLboolean newline)
1282{
1283   static int debug = -1;
1284
1285   /* Init the local 'debug' var once.
1286    * Note: the _mesa_init_debug() function should have been called
1287    * by now so MESA_DEBUG_FLAGS will be initialized.
1288    */
1289   if (debug == -1) {
1290      /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
1291       * etc to the named file.  Otherwise, output to stderr.
1292       */
1293      const char *logFile = getenv("MESA_LOG_FILE");
1294      if (logFile)
1295         LogFile = fopen(logFile, "w");
1296      if (!LogFile)
1297         LogFile = stderr;
1298#ifdef DEBUG
1299      /* in debug builds, print messages unless MESA_DEBUG="silent" */
1300      if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
1301         debug = 0;
1302      else
1303         debug = 1;
1304#else
1305      /* in release builds, be silent unless MESA_DEBUG is set */
1306      debug = getenv("MESA_DEBUG") != NULL;
1307#endif
1308   }
1309
1310   /* Now only print the string if we're required to do so. */
1311   if (debug) {
1312      if (prefixString)
1313         fprintf(LogFile, "%s: %s", prefixString, outputString);
1314      else
1315         fprintf(LogFile, "%s", outputString);
1316      if (newline)
1317         fprintf(LogFile, "\n");
1318      fflush(LogFile);
1319
1320#if defined(_WIN32)
1321      /* stderr from windows applications without console is not usually
1322       * visible, so communicate with the debugger instead */
1323      {
1324         char buf[4096];
1325         _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
1326         OutputDebugStringA(buf);
1327      }
1328#endif
1329   }
1330}
1331
1332
1333/**
1334 * Return the file handle to use for debug/logging.  Defaults to stderr
1335 * unless MESA_LOG_FILE is defined.
1336 */
1337FILE *
1338_mesa_get_log_file(void)
1339{
1340   assert(LogFile);
1341   return LogFile;
1342}
1343
1344
1345/**
1346 * When a new type of error is recorded, print a message describing
1347 * previous errors which were accumulated.
1348 */
1349static void
1350flush_delayed_errors( struct gl_context *ctx )
1351{
1352   char s[MAX_DEBUG_MESSAGE_LENGTH];
1353
1354   if (ctx->ErrorDebugCount) {
1355      _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors",
1356                     ctx->ErrorDebugCount,
1357                     _mesa_enum_to_string(ctx->ErrorValue));
1358
1359      output_if_debug("Mesa", s, GL_TRUE);
1360
1361      ctx->ErrorDebugCount = 0;
1362   }
1363}
1364
1365
1366/**
1367 * Report a warning (a recoverable error condition) to stderr if
1368 * either DEBUG is defined or the MESA_DEBUG env var is set.
1369 *
1370 * \param ctx GL context.
1371 * \param fmtString printf()-like format string.
1372 */
1373void
1374_mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
1375{
1376   char str[MAX_DEBUG_MESSAGE_LENGTH];
1377   va_list args;
1378   va_start( args, fmtString );
1379   (void) _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
1380   va_end( args );
1381
1382   if (ctx)
1383      flush_delayed_errors( ctx );
1384
1385   output_if_debug("Mesa warning", str, GL_TRUE);
1386}
1387
1388
1389/**
1390 * Report an internal implementation problem.
1391 * Prints the message to stderr via fprintf().
1392 *
1393 * \param ctx GL context.
1394 * \param fmtString problem description string.
1395 */
1396void
1397_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
1398{
1399   va_list args;
1400   char str[MAX_DEBUG_MESSAGE_LENGTH];
1401   static int numCalls = 0;
1402
1403   (void) ctx;
1404
1405   if (numCalls < 50) {
1406      numCalls++;
1407
1408      va_start( args, fmtString );
1409      _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
1410      va_end( args );
1411      fprintf(stderr, "Mesa %s implementation error: %s\n",
1412              PACKAGE_VERSION, str);
1413      fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n");
1414   }
1415}
1416
1417
1418static GLboolean
1419should_output(struct gl_context *ctx, GLenum error, const char *fmtString)
1420{
1421   static GLint debug = -1;
1422
1423   /* Check debug environment variable only once:
1424    */
1425   if (debug == -1) {
1426      const char *debugEnv = getenv("MESA_DEBUG");
1427
1428#ifdef DEBUG
1429      if (debugEnv && strstr(debugEnv, "silent"))
1430         debug = GL_FALSE;
1431      else
1432         debug = GL_TRUE;
1433#else
1434      if (debugEnv)
1435         debug = GL_TRUE;
1436      else
1437         debug = GL_FALSE;
1438#endif
1439   }
1440
1441   if (debug) {
1442      if (ctx->ErrorValue != error ||
1443          ctx->ErrorDebugFmtString != fmtString) {
1444         flush_delayed_errors( ctx );
1445         ctx->ErrorDebugFmtString = fmtString;
1446         ctx->ErrorDebugCount = 0;
1447         return GL_TRUE;
1448      }
1449      ctx->ErrorDebugCount++;
1450   }
1451   return GL_FALSE;
1452}
1453
1454
1455void
1456_mesa_gl_vdebug(struct gl_context *ctx,
1457                GLuint *id,
1458                enum mesa_debug_source source,
1459                enum mesa_debug_type type,
1460                enum mesa_debug_severity severity,
1461                const char *fmtString,
1462                va_list args)
1463{
1464   char s[MAX_DEBUG_MESSAGE_LENGTH];
1465   int len;
1466
1467   debug_get_id(id);
1468
1469   len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1470
1471   log_msg(ctx, source, type, *id, severity, len, s);
1472}
1473
1474
1475void
1476_mesa_gl_debug(struct gl_context *ctx,
1477               GLuint *id,
1478               enum mesa_debug_source source,
1479               enum mesa_debug_type type,
1480               enum mesa_debug_severity severity,
1481               const char *fmtString, ...)
1482{
1483   va_list args;
1484   va_start(args, fmtString);
1485   _mesa_gl_vdebug(ctx, id, source, type, severity, fmtString, args);
1486   va_end(args);
1487}
1488
1489
1490/**
1491 * Record an OpenGL state error.  These usually occur when the user
1492 * passes invalid parameters to a GL function.
1493 *
1494 * If debugging is enabled (either at compile-time via the DEBUG macro, or
1495 * run-time via the MESA_DEBUG environment variable), report the error with
1496 * _mesa_debug().
1497 *
1498 * \param ctx the GL context.
1499 * \param error the error value.
1500 * \param fmtString printf() style format string, followed by optional args
1501 */
1502void
1503_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
1504{
1505   GLboolean do_output, do_log;
1506   /* Ideally this would be set up by the caller, so that we had proper IDs
1507    * per different message.
1508    */
1509   static GLuint error_msg_id = 0;
1510
1511   debug_get_id(&error_msg_id);
1512
1513   do_output = should_output(ctx, error, fmtString);
1514
1515   mtx_lock(&ctx->DebugMutex);
1516   if (ctx->Debug) {
1517      do_log = debug_is_message_enabled(ctx->Debug,
1518                                        MESA_DEBUG_SOURCE_API,
1519                                        MESA_DEBUG_TYPE_ERROR,
1520                                        error_msg_id,
1521                                        MESA_DEBUG_SEVERITY_HIGH);
1522   }
1523   else {
1524      do_log = GL_FALSE;
1525   }
1526   mtx_unlock(&ctx->DebugMutex);
1527
1528   if (do_output || do_log) {
1529      char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
1530      int len;
1531      va_list args;
1532
1533      va_start(args, fmtString);
1534      len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1535      va_end(args);
1536
1537      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
1538         /* Too long error message. Whoever calls _mesa_error should use
1539          * shorter strings.
1540          */
1541         assert(0);
1542         return;
1543      }
1544
1545      len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
1546                           _mesa_enum_to_string(error), s);
1547      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
1548         /* Same as above. */
1549         assert(0);
1550         return;
1551      }
1552
1553      /* Print the error to stderr if needed. */
1554      if (do_output) {
1555         output_if_debug("Mesa: User error", s2, GL_TRUE);
1556      }
1557
1558      /* Log the error via ARB_debug_output if needed.*/
1559      if (do_log) {
1560         log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR,
1561                 error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2);
1562      }
1563   }
1564
1565   /* Set the GL context error state for glGetError. */
1566   _mesa_record_error(ctx, error);
1567}
1568
1569void
1570_mesa_error_no_memory(const char *caller)
1571{
1572   GET_CURRENT_CONTEXT(ctx);
1573   _mesa_error(ctx, GL_OUT_OF_MEMORY, "out of memory in %s", caller);
1574}
1575
1576/**
1577 * Report debug information.  Print error message to stderr via fprintf().
1578 * No-op if DEBUG mode not enabled.
1579 *
1580 * \param ctx GL context.
1581 * \param fmtString printf()-style format string, followed by optional args.
1582 */
1583void
1584_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
1585{
1586#ifdef DEBUG
1587   char s[MAX_DEBUG_MESSAGE_LENGTH];
1588   va_list args;
1589   va_start(args, fmtString);
1590   _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1591   va_end(args);
1592   output_if_debug("Mesa", s, GL_FALSE);
1593#endif /* DEBUG */
1594   (void) ctx;
1595   (void) fmtString;
1596}
1597
1598
1599void
1600_mesa_log(const char *fmtString, ...)
1601{
1602   char s[MAX_DEBUG_MESSAGE_LENGTH];
1603   va_list args;
1604   va_start(args, fmtString);
1605   _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1606   va_end(args);
1607   output_if_debug("", s, GL_FALSE);
1608}
1609
1610
1611/**
1612 * Report debug information from the shader compiler via GL_ARB_debug_output.
1613 *
1614 * \param ctx GL context.
1615 * \param type The namespace to which this message belongs.
1616 * \param id The message ID within the given namespace.
1617 * \param msg The message to output. Must be null-terminated.
1618 */
1619void
1620_mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id,
1621                   const char *msg)
1622{
1623   enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
1624   enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH;
1625   int len;
1626
1627   debug_get_id(id);
1628
1629   len = strlen(msg);
1630
1631   /* Truncate the message if necessary. */
1632   if (len >= MAX_DEBUG_MESSAGE_LENGTH)
1633      len = MAX_DEBUG_MESSAGE_LENGTH - 1;
1634
1635   log_msg(ctx, source, type, *id, severity, len, msg);
1636}
1637
1638/*@}*/
1639