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