1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2016  Brian Paul, et al   All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26#include <stdarg.h>
27#include <stdio.h>
28#include "context.h"
29#include "debug_output.h"
30#include "dispatch.h"
31#include "enums.h"
32#include "imports.h"
33#include "hash.h"
34#include "mtypes.h"
35#include "version.h"
36#include "util/hash_table.h"
37#include "util/simple_list.h"
38
39
40static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP;
41static GLuint NextDynamicID = 1;
42
43
44/**
45 * A namespace element.
46 */
47struct gl_debug_element
48{
49   struct simple_node link;
50
51   GLuint ID;
52   /* at which severity levels (mesa_debug_severity) is the message enabled */
53   GLbitfield State;
54};
55
56
57struct gl_debug_namespace
58{
59   struct simple_node Elements;
60   GLbitfield DefaultState;
61};
62
63
64struct gl_debug_group {
65   struct gl_debug_namespace Namespaces[MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
66};
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/**
87 * Debug message log.  It works like a ring buffer.
88 */
89struct gl_debug_log {
90   struct gl_debug_message Messages[MAX_DEBUG_LOGGED_MESSAGES];
91   GLint NextMessage;
92   GLint NumMessages;
93};
94
95
96struct gl_debug_state
97{
98   GLDEBUGPROC Callback;
99   const void *CallbackData;
100   GLboolean SyncOutput;
101   GLboolean DebugOutput;
102   GLboolean LogToStderr;
103
104   struct gl_debug_group *Groups[MAX_DEBUG_GROUP_STACK_DEPTH];
105   struct gl_debug_message GroupMessages[MAX_DEBUG_GROUP_STACK_DEPTH];
106   GLint CurrentGroup; // GroupStackDepth - 1
107
108   struct gl_debug_log Log;
109};
110
111
112static char out_of_memory[] = "Debugging error: out of memory";
113
114static const GLenum debug_source_enums[] = {
115   GL_DEBUG_SOURCE_API,
116   GL_DEBUG_SOURCE_WINDOW_SYSTEM,
117   GL_DEBUG_SOURCE_SHADER_COMPILER,
118   GL_DEBUG_SOURCE_THIRD_PARTY,
119   GL_DEBUG_SOURCE_APPLICATION,
120   GL_DEBUG_SOURCE_OTHER,
121};
122
123static const GLenum debug_type_enums[] = {
124   GL_DEBUG_TYPE_ERROR,
125   GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
126   GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
127   GL_DEBUG_TYPE_PORTABILITY,
128   GL_DEBUG_TYPE_PERFORMANCE,
129   GL_DEBUG_TYPE_OTHER,
130   GL_DEBUG_TYPE_MARKER,
131   GL_DEBUG_TYPE_PUSH_GROUP,
132   GL_DEBUG_TYPE_POP_GROUP,
133};
134
135static const GLenum debug_severity_enums[] = {
136   GL_DEBUG_SEVERITY_LOW,
137   GL_DEBUG_SEVERITY_MEDIUM,
138   GL_DEBUG_SEVERITY_HIGH,
139   GL_DEBUG_SEVERITY_NOTIFICATION,
140};
141
142
143static enum mesa_debug_source
144gl_enum_to_debug_source(GLenum e)
145{
146   unsigned i;
147
148   for (i = 0; i < ARRAY_SIZE(debug_source_enums); i++) {
149      if (debug_source_enums[i] == e)
150         break;
151   }
152   return i;
153}
154
155static enum mesa_debug_type
156gl_enum_to_debug_type(GLenum e)
157{
158   unsigned i;
159
160   for (i = 0; i < ARRAY_SIZE(debug_type_enums); i++) {
161      if (debug_type_enums[i] == e)
162         break;
163   }
164   return i;
165}
166
167static enum mesa_debug_severity
168gl_enum_to_debug_severity(GLenum e)
169{
170   unsigned i;
171
172   for (i = 0; i < ARRAY_SIZE(debug_severity_enums); i++) {
173      if (debug_severity_enums[i] == e)
174         break;
175   }
176   return i;
177}
178
179
180/**
181 * Handles generating a GL_ARB_debug_output message ID generated by the GL or
182 * GLSL compiler.
183 *
184 * The GL API has this "ID" mechanism, where the intention is to allow a
185 * client to filter in/out messages based on source, type, and ID.  Of course,
186 * building a giant enum list of all debug output messages that Mesa might
187 * generate is ridiculous, so instead we have our caller pass us a pointer to
188 * static storage where the ID should get stored.  This ID will be shared
189 * across all contexts for that message (which seems like a desirable
190 * property, even if it's not expected by the spec), but note that it won't be
191 * the same between executions if messages aren't generated in the same order.
192 */
193void
194_mesa_debug_get_id(GLuint *id)
195{
196   if (!(*id)) {
197      mtx_lock(&DynamicIDMutex);
198      if (!(*id))
199         *id = NextDynamicID++;
200      mtx_unlock(&DynamicIDMutex);
201   }
202}
203
204static void
205debug_message_clear(struct gl_debug_message *msg)
206{
207   if (msg->message != (char*)out_of_memory)
208      free(msg->message);
209   msg->message = NULL;
210   msg->length = 0;
211}
212
213static void
214debug_message_store(struct gl_debug_message *msg,
215                    enum mesa_debug_source source,
216                    enum mesa_debug_type type, GLuint id,
217                    enum mesa_debug_severity severity,
218                    GLsizei len, const char *buf)
219{
220   GLsizei length = len;
221
222   assert(!msg->message && !msg->length);
223
224   if (length < 0)
225      length = strlen(buf);
226
227   msg->message = malloc(length+1);
228   if (msg->message) {
229      (void) strncpy(msg->message, buf, (size_t)length);
230      msg->message[length] = '\0';
231
232      msg->length = len;
233      msg->source = source;
234      msg->type = type;
235      msg->id = id;
236      msg->severity = severity;
237   } else {
238      static GLuint oom_msg_id = 0;
239      _mesa_debug_get_id(&oom_msg_id);
240
241      /* malloc failed! */
242      msg->message = out_of_memory;
243      msg->length = -1;
244      msg->source = MESA_DEBUG_SOURCE_OTHER;
245      msg->type = MESA_DEBUG_TYPE_ERROR;
246      msg->id = oom_msg_id;
247      msg->severity = MESA_DEBUG_SEVERITY_HIGH;
248   }
249}
250
251static void
252debug_namespace_init(struct gl_debug_namespace *ns)
253{
254   make_empty_list(&ns->Elements);
255
256   /* Enable all the messages with severity HIGH or MEDIUM by default */
257   ns->DefaultState = (1 << MESA_DEBUG_SEVERITY_MEDIUM ) |
258                      (1 << MESA_DEBUG_SEVERITY_HIGH) |
259                      (1 << MESA_DEBUG_SEVERITY_NOTIFICATION);
260}
261
262static void
263debug_namespace_clear(struct gl_debug_namespace *ns)
264{
265   struct simple_node *node, *tmp;
266
267   foreach_s(node, tmp, &ns->Elements)
268      free(node);
269}
270
271static bool
272debug_namespace_copy(struct gl_debug_namespace *dst,
273                     const struct gl_debug_namespace *src)
274{
275   struct simple_node *node;
276
277   dst->DefaultState = src->DefaultState;
278
279   make_empty_list(&dst->Elements);
280   foreach(node, &src->Elements) {
281      const struct gl_debug_element *elem =
282         (const struct gl_debug_element *) node;
283      struct gl_debug_element *copy;
284
285      copy = malloc(sizeof(*copy));
286      if (!copy) {
287         debug_namespace_clear(dst);
288         return false;
289      }
290
291      copy->ID = elem->ID;
292      copy->State = elem->State;
293      insert_at_tail(&dst->Elements, &copy->link);
294   }
295
296   return true;
297}
298
299/**
300 * Set the state of \p id in the namespace.
301 */
302static bool
303debug_namespace_set(struct gl_debug_namespace *ns,
304                    GLuint id, bool enabled)
305{
306   const uint32_t state = (enabled) ?
307      ((1 << MESA_DEBUG_SEVERITY_COUNT) - 1) : 0;
308   struct gl_debug_element *elem = NULL;
309   struct simple_node *node;
310
311   /* find the element */
312   foreach(node, &ns->Elements) {
313      struct gl_debug_element *tmp = (struct gl_debug_element *) node;
314      if (tmp->ID == id) {
315         elem = tmp;
316         break;
317      }
318   }
319
320   /* we do not need the element if it has the default state */
321   if (ns->DefaultState == state) {
322      if (elem) {
323         remove_from_list(&elem->link);
324         free(elem);
325      }
326      return true;
327   }
328
329   if (!elem) {
330      elem = malloc(sizeof(*elem));
331      if (!elem)
332         return false;
333
334      elem->ID = id;
335      insert_at_tail(&ns->Elements, &elem->link);
336   }
337
338   elem->State = state;
339
340   return true;
341}
342
343/**
344 * Set the default state of the namespace for \p severity.  When \p severity
345 * is MESA_DEBUG_SEVERITY_COUNT, the default values for all severities are
346 * updated.
347 */
348static void
349debug_namespace_set_all(struct gl_debug_namespace *ns,
350                        enum mesa_debug_severity severity,
351                        bool enabled)
352{
353   struct simple_node *node, *tmp;
354   uint32_t mask, val;
355
356   /* set all elements to the same state */
357   if (severity == MESA_DEBUG_SEVERITY_COUNT) {
358      ns->DefaultState = (enabled) ? ((1 << severity) - 1) : 0;
359      debug_namespace_clear(ns);
360      make_empty_list(&ns->Elements);
361      return;
362   }
363
364   mask = 1 << severity;
365   val = (enabled) ? mask : 0;
366
367   ns->DefaultState = (ns->DefaultState & ~mask) | val;
368
369   foreach_s(node, tmp, &ns->Elements) {
370      struct gl_debug_element *elem = (struct gl_debug_element *) node;
371
372      elem->State = (elem->State & ~mask) | val;
373      if (elem->State == ns->DefaultState) {
374         remove_from_list(node);
375         free(node);
376      }
377   }
378}
379
380/**
381 * Get the state of \p id in the namespace.
382 */
383static bool
384debug_namespace_get(const struct gl_debug_namespace *ns, GLuint id,
385                    enum mesa_debug_severity severity)
386{
387   struct simple_node *node;
388   uint32_t state;
389
390   state = ns->DefaultState;
391   foreach(node, &ns->Elements) {
392      struct gl_debug_element *elem = (struct gl_debug_element *) node;
393
394      if (elem->ID == id) {
395         state = elem->State;
396         break;
397      }
398   }
399
400   return (state & (1 << severity));
401}
402
403/**
404 * Allocate and initialize context debug state.
405 */
406static struct gl_debug_state *
407debug_create(void)
408{
409   struct gl_debug_state *debug;
410   int s, t;
411
412   debug = CALLOC_STRUCT(gl_debug_state);
413   if (!debug)
414      return NULL;
415
416   debug->Groups[0] = malloc(sizeof(*debug->Groups[0]));
417   if (!debug->Groups[0]) {
418      free(debug);
419      return NULL;
420   }
421
422   /* Initialize state for filtering known debug messages. */
423   for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
424      for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
425         debug_namespace_init(&debug->Groups[0]->Namespaces[s][t]);
426   }
427
428   return debug;
429}
430
431/**
432 * Return true if the top debug group points to the group below it.
433 */
434static bool
435debug_is_group_read_only(const struct gl_debug_state *debug)
436{
437   const GLint gstack = debug->CurrentGroup;
438   return (gstack > 0 && debug->Groups[gstack] == debug->Groups[gstack - 1]);
439}
440
441/**
442 * Make the top debug group writable.
443 */
444static bool
445debug_make_group_writable(struct gl_debug_state *debug)
446{
447   const GLint gstack = debug->CurrentGroup;
448   const struct gl_debug_group *src = debug->Groups[gstack];
449   struct gl_debug_group *dst;
450   int s, t;
451
452   if (!debug_is_group_read_only(debug))
453      return true;
454
455   dst = malloc(sizeof(*dst));
456   if (!dst)
457      return false;
458
459   for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
460      for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
461         if (!debug_namespace_copy(&dst->Namespaces[s][t],
462                                   &src->Namespaces[s][t])) {
463            /* error path! */
464            for (t = t - 1; t >= 0; t--)
465               debug_namespace_clear(&dst->Namespaces[s][t]);
466            for (s = s - 1; s >= 0; s--) {
467               for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
468                  debug_namespace_clear(&dst->Namespaces[s][t]);
469            }
470            free(dst);
471            return false;
472         }
473      }
474   }
475
476   debug->Groups[gstack] = dst;
477
478   return true;
479}
480
481/**
482 * Free the top debug group.
483 */
484static void
485debug_clear_group(struct gl_debug_state *debug)
486{
487   const GLint gstack = debug->CurrentGroup;
488
489   if (!debug_is_group_read_only(debug)) {
490      struct gl_debug_group *grp = debug->Groups[gstack];
491      int s, t;
492
493      for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
494         for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
495            debug_namespace_clear(&grp->Namespaces[s][t]);
496      }
497
498      free(grp);
499   }
500
501   debug->Groups[gstack] = NULL;
502}
503
504/**
505 * Loop through debug group stack tearing down states for
506 * filtering debug messages.  Then free debug output state.
507 */
508static void
509debug_destroy(struct gl_debug_state *debug)
510{
511   while (debug->CurrentGroup > 0) {
512      debug_clear_group(debug);
513      debug->CurrentGroup--;
514   }
515
516   debug_clear_group(debug);
517   free(debug);
518}
519
520/**
521 * Sets the state of the given message source/type/ID tuple.
522 */
523static void
524debug_set_message_enable(struct gl_debug_state *debug,
525                         enum mesa_debug_source source,
526                         enum mesa_debug_type type,
527                         GLuint id, GLboolean enabled)
528{
529   const GLint gstack = debug->CurrentGroup;
530   struct gl_debug_namespace *ns;
531
532   debug_make_group_writable(debug);
533   ns = &debug->Groups[gstack]->Namespaces[source][type];
534
535   debug_namespace_set(ns, id, enabled);
536}
537
538/*
539 * Set the state of all message IDs found in the given intersection of
540 * 'source', 'type', and 'severity'.  The _COUNT enum can be used for
541 * GL_DONT_CARE (include all messages in the class).
542 *
543 * This requires both setting the state of all previously seen message
544 * IDs in the hash table, and setting the default state for all
545 * applicable combinations of source/type/severity, so that all the
546 * yet-unknown message IDs that may be used in the future will be
547 * impacted as if they were already known.
548 */
549static void
550debug_set_message_enable_all(struct gl_debug_state *debug,
551                             enum mesa_debug_source source,
552                             enum mesa_debug_type type,
553                             enum mesa_debug_severity severity,
554                             GLboolean enabled)
555{
556   const GLint gstack = debug->CurrentGroup;
557   int s, t, smax, tmax;
558
559   if (source == MESA_DEBUG_SOURCE_COUNT) {
560      source = 0;
561      smax = MESA_DEBUG_SOURCE_COUNT;
562   } else {
563      smax = source+1;
564   }
565
566   if (type == MESA_DEBUG_TYPE_COUNT) {
567      type = 0;
568      tmax = MESA_DEBUG_TYPE_COUNT;
569   } else {
570      tmax = type+1;
571   }
572
573   debug_make_group_writable(debug);
574
575   for (s = source; s < smax; s++) {
576      for (t = type; t < tmax; t++) {
577         struct gl_debug_namespace *nspace =
578            &debug->Groups[gstack]->Namespaces[s][t];
579         debug_namespace_set_all(nspace, severity, enabled);
580      }
581   }
582}
583
584/**
585 * Returns if the given message source/type/ID tuple is enabled.
586 */
587bool
588_mesa_debug_is_message_enabled(const struct gl_debug_state *debug,
589                               enum mesa_debug_source source,
590                               enum mesa_debug_type type,
591                               GLuint id,
592                               enum mesa_debug_severity severity)
593{
594   const GLint gstack = debug->CurrentGroup;
595   struct gl_debug_group *grp = debug->Groups[gstack];
596   struct gl_debug_namespace *nspace = &grp->Namespaces[source][type];
597
598   if (!debug->DebugOutput)
599      return false;
600
601   return debug_namespace_get(nspace, id, severity);
602}
603
604/**
605 * 'buf' is not necessarily a null-terminated string. When logging, copy
606 * 'len' characters from it, store them in a new, null-terminated string,
607 * and remember the number of bytes used by that string, *including*
608 * the null terminator this time.
609 */
610static void
611debug_log_message(struct gl_debug_state *debug,
612                  enum mesa_debug_source source,
613                  enum mesa_debug_type type, GLuint id,
614                  enum mesa_debug_severity severity,
615                  GLsizei len, const char *buf)
616{
617   struct gl_debug_log *log = &debug->Log;
618   GLint nextEmpty;
619   struct gl_debug_message *emptySlot;
620
621   if (debug->LogToStderr) {
622      _mesa_log("Mesa debug output: %.*s\n", len, buf);
623   }
624
625   assert(len < MAX_DEBUG_MESSAGE_LENGTH);
626
627   if (log->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
628      return;
629
630   nextEmpty = (log->NextMessage + log->NumMessages)
631      % MAX_DEBUG_LOGGED_MESSAGES;
632   emptySlot = &log->Messages[nextEmpty];
633
634   debug_message_store(emptySlot, source, type,
635                       id, severity, len, buf);
636
637   log->NumMessages++;
638}
639
640/**
641 * Return the oldest debug message out of the log.
642 */
643static const struct gl_debug_message *
644debug_fetch_message(const struct gl_debug_state *debug)
645{
646   const struct gl_debug_log *log = &debug->Log;
647
648   return (log->NumMessages) ? &log->Messages[log->NextMessage] : NULL;
649}
650
651/**
652 * Delete the oldest debug messages out of the log.
653 */
654static void
655debug_delete_messages(struct gl_debug_state *debug, int count)
656{
657   struct gl_debug_log *log = &debug->Log;
658
659   if (count > log->NumMessages)
660      count = log->NumMessages;
661
662   while (count--) {
663      struct gl_debug_message *msg = &log->Messages[log->NextMessage];
664
665      debug_message_clear(msg);
666
667      log->NumMessages--;
668      log->NextMessage++;
669      log->NextMessage %= MAX_DEBUG_LOGGED_MESSAGES;
670   }
671}
672
673static struct gl_debug_message *
674debug_get_group_message(struct gl_debug_state *debug)
675{
676   return &debug->GroupMessages[debug->CurrentGroup];
677}
678
679static void
680debug_push_group(struct gl_debug_state *debug)
681{
682   const GLint gstack = debug->CurrentGroup;
683
684   /* just point to the previous stack */
685   debug->Groups[gstack + 1] = debug->Groups[gstack];
686   debug->CurrentGroup++;
687}
688
689static void
690debug_pop_group(struct gl_debug_state *debug)
691{
692   debug_clear_group(debug);
693   debug->CurrentGroup--;
694}
695
696
697/**
698 * Lock and return debug state for the context.  The debug state will be
699 * allocated and initialized upon the first call.  When NULL is returned, the
700 * debug state is not locked.
701 */
702static struct gl_debug_state *
703_mesa_lock_debug_state(struct gl_context *ctx)
704{
705   mtx_lock(&ctx->DebugMutex);
706
707   if (!ctx->Debug) {
708      ctx->Debug = debug_create();
709      if (!ctx->Debug) {
710         GET_CURRENT_CONTEXT(cur);
711         mtx_unlock(&ctx->DebugMutex);
712
713         /*
714          * This function may be called from other threads.  When that is the
715          * case, we cannot record this OOM error.
716          */
717         if (ctx == cur)
718            _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
719
720         return NULL;
721      }
722   }
723
724   return ctx->Debug;
725}
726
727static void
728_mesa_unlock_debug_state(struct gl_context *ctx)
729{
730   mtx_unlock(&ctx->DebugMutex);
731}
732
733/**
734 * Set the integer debug state specified by \p pname.  This can be called from
735 * _mesa_set_enable for example.
736 */
737bool
738_mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val)
739{
740   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
741
742   if (!debug)
743      return false;
744
745   switch (pname) {
746   case GL_DEBUG_OUTPUT:
747      debug->DebugOutput = (val != 0);
748      break;
749   case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
750      debug->SyncOutput = (val != 0);
751      break;
752   default:
753      assert(!"unknown debug output param");
754      break;
755   }
756
757   _mesa_unlock_debug_state(ctx);
758
759   return true;
760}
761
762/**
763 * Query the integer debug state specified by \p pname.  This can be called
764 * _mesa_GetIntegerv for example.
765 */
766GLint
767_mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
768{
769   GLint val;
770
771   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
772   if (!debug)
773      return 0;
774
775   switch (pname) {
776   case GL_DEBUG_OUTPUT:
777      val = debug->DebugOutput;
778      break;
779   case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
780      val = debug->SyncOutput;
781      break;
782   case GL_DEBUG_LOGGED_MESSAGES:
783      val = debug->Log.NumMessages;
784      break;
785   case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
786      val = (debug->Log.NumMessages) ?
787         debug->Log.Messages[debug->Log.NextMessage].length + 1 : 0;
788      break;
789   case GL_DEBUG_GROUP_STACK_DEPTH:
790      val = debug->CurrentGroup + 1;
791      break;
792   default:
793      assert(!"unknown debug output param");
794      val = 0;
795      break;
796   }
797
798   _mesa_unlock_debug_state(ctx);
799
800   return val;
801}
802
803/**
804 * Query the pointer debug state specified by \p pname.  This can be called
805 * _mesa_GetPointerv for example.
806 */
807void *
808_mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname)
809{
810   void *val;
811   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
812
813   if (!debug)
814      return NULL;
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   _mesa_unlock_debug_state(ctx);
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 (!_mesa_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      /* Call the user's callback function */
854      GLenum gl_source = debug_source_enums[source];
855      GLenum gl_type = debug_type_enums[type];
856      GLenum gl_severity = debug_severity_enums[severity];
857      GLDEBUGPROC callback = ctx->Debug->Callback;
858      const void *data = ctx->Debug->CallbackData;
859
860      /*
861       * When ctx->Debug->SyncOutput is GL_FALSE, the client is prepared for
862       * unsynchronous calls.  When it is GL_TRUE, we will not spawn threads.
863       * In either case, we can call the callback unlocked.
864       */
865      _mesa_unlock_debug_state(ctx);
866      callback(gl_source, gl_type, id, gl_severity, len, buf, data);
867   }
868   else {
869      /* add debug message to queue */
870      debug_log_message(ctx->Debug, source, type, id, severity, len, buf);
871      _mesa_unlock_debug_state(ctx);
872   }
873}
874
875/**
876 * Log a client or driver debug message.
877 */
878void
879_mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source,
880              enum mesa_debug_type type, GLuint id,
881              enum mesa_debug_severity severity, GLint len, const char *buf)
882{
883   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
884
885   if (!debug)
886      return;
887
888   log_msg_locked_and_unlock(ctx, source, type, id, severity, len, buf);
889}
890
891
892/**
893 * Verify that source, type, and severity are valid enums.
894 *
895 * The 'caller' param is used for handling values available
896 * only in glDebugMessageInsert or glDebugMessageControl
897 */
898static GLboolean
899validate_params(struct gl_context *ctx, unsigned caller,
900                const char *callerstr, GLenum source, GLenum type,
901                GLenum severity)
902{
903#define INSERT 1
904#define CONTROL 2
905   switch(source) {
906   case GL_DEBUG_SOURCE_APPLICATION_ARB:
907   case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
908      break;
909   case GL_DEBUG_SOURCE_API_ARB:
910   case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
911   case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
912   case GL_DEBUG_SOURCE_OTHER_ARB:
913      if (caller != INSERT)
914         break;
915      else
916         goto error;
917   case GL_DONT_CARE:
918      if (caller == CONTROL)
919         break;
920      else
921         goto error;
922   default:
923      goto error;
924   }
925
926   switch(type) {
927   case GL_DEBUG_TYPE_ERROR_ARB:
928   case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
929   case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
930   case GL_DEBUG_TYPE_PERFORMANCE_ARB:
931   case GL_DEBUG_TYPE_PORTABILITY_ARB:
932   case GL_DEBUG_TYPE_OTHER_ARB:
933   case GL_DEBUG_TYPE_MARKER:
934   case GL_DEBUG_TYPE_PUSH_GROUP:
935   case GL_DEBUG_TYPE_POP_GROUP:
936      break;
937   case GL_DONT_CARE:
938      if (caller == CONTROL)
939         break;
940      else
941         goto error;
942   default:
943      goto error;
944   }
945
946   switch(severity) {
947   case GL_DEBUG_SEVERITY_HIGH_ARB:
948   case GL_DEBUG_SEVERITY_MEDIUM_ARB:
949   case GL_DEBUG_SEVERITY_LOW_ARB:
950   case GL_DEBUG_SEVERITY_NOTIFICATION:
951      break;
952   case GL_DONT_CARE:
953      if (caller == CONTROL)
954         break;
955      else
956         goto error;
957   default:
958      goto error;
959   }
960   return GL_TRUE;
961
962error:
963   _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s"
964               "(source=0x%x, type=0x%x, severity=0x%x)", callerstr,
965               source, type, severity);
966
967   return GL_FALSE;
968}
969
970
971static GLboolean
972validate_length(struct gl_context *ctx, const char *callerstr, GLsizei length,
973                const GLchar *buf)
974{
975
976   if (length < 0) {
977      GLsizei len = strlen(buf);
978
979      if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
980         _mesa_error(ctx, GL_INVALID_VALUE,
981                    "%s(null terminated string length=%d, is not less than "
982                    "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, len,
983                    MAX_DEBUG_MESSAGE_LENGTH);
984         return GL_FALSE;
985      }
986   }
987
988   if (length >= MAX_DEBUG_MESSAGE_LENGTH) {
989      _mesa_error(ctx, GL_INVALID_VALUE,
990                 "%s(length=%d, which is not less than "
991                 "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, length,
992                 MAX_DEBUG_MESSAGE_LENGTH);
993      return GL_FALSE;
994   }
995
996   return GL_TRUE;
997}
998
999
1000void GLAPIENTRY
1001_mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
1002                         GLenum severity, GLint length,
1003                         const GLchar *buf)
1004{
1005   GET_CURRENT_CONTEXT(ctx);
1006   const char *callerstr;
1007
1008   if (_mesa_is_desktop_gl(ctx))
1009      callerstr = "glDebugMessageInsert";
1010   else
1011      callerstr = "glDebugMessageInsertKHR";
1012
1013   if (!validate_params(ctx, INSERT, callerstr, source, type, severity))
1014      return; /* GL_INVALID_ENUM */
1015
1016   if (!validate_length(ctx, callerstr, length, buf))
1017      return; /* GL_INVALID_VALUE */
1018
1019   /* if length not specified, string will be null terminated: */
1020   if (length < 0)
1021      length = strlen(buf);
1022
1023   _mesa_log_msg(ctx, gl_enum_to_debug_source(source),
1024                 gl_enum_to_debug_type(type), id,
1025                 gl_enum_to_debug_severity(severity),
1026                 length, buf);
1027
1028   if (type == GL_DEBUG_TYPE_MARKER && ctx->Driver.EmitStringMarker) {
1029      ctx->Driver.EmitStringMarker(ctx, buf, length);
1030   }
1031}
1032
1033
1034GLuint GLAPIENTRY
1035_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
1036                         GLenum *types, GLenum *ids, GLenum *severities,
1037                         GLsizei *lengths, GLchar *messageLog)
1038{
1039   GET_CURRENT_CONTEXT(ctx);
1040   struct gl_debug_state *debug;
1041   const char *callerstr;
1042   GLuint ret;
1043
1044   if (_mesa_is_desktop_gl(ctx))
1045      callerstr = "glGetDebugMessageLog";
1046   else
1047      callerstr = "glGetDebugMessageLogKHR";
1048
1049   if (!messageLog)
1050      logSize = 0;
1051
1052   if (logSize < 0) {
1053      _mesa_error(ctx, GL_INVALID_VALUE,
1054                  "%s(logSize=%d : logSize must not be negative)",
1055                  callerstr, logSize);
1056      return 0;
1057   }
1058
1059   debug = _mesa_lock_debug_state(ctx);
1060   if (!debug)
1061      return 0;
1062
1063   for (ret = 0; ret < count; ret++) {
1064      const struct gl_debug_message *msg = debug_fetch_message(debug);
1065      GLsizei len;
1066
1067      if (!msg)
1068         break;
1069
1070      len = msg->length;
1071      if (len < 0)
1072         len = strlen(msg->message);
1073
1074      if (logSize < len+1 && messageLog != NULL)
1075         break;
1076
1077      if (messageLog) {
1078         assert(msg->message[len] == '\0');
1079         (void) strncpy(messageLog, msg->message, (size_t)len+1);
1080
1081         messageLog += len+1;
1082         logSize -= len+1;
1083      }
1084
1085      if (lengths)
1086         *lengths++ = len+1;
1087      if (severities)
1088         *severities++ = debug_severity_enums[msg->severity];
1089      if (sources)
1090         *sources++ = debug_source_enums[msg->source];
1091      if (types)
1092         *types++ = debug_type_enums[msg->type];
1093      if (ids)
1094         *ids++ = msg->id;
1095
1096      debug_delete_messages(debug, 1);
1097   }
1098
1099   _mesa_unlock_debug_state(ctx);
1100
1101   return ret;
1102}
1103
1104
1105void GLAPIENTRY
1106_mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
1107                          GLenum gl_severity, GLsizei count,
1108                          const GLuint *ids, GLboolean enabled)
1109{
1110   GET_CURRENT_CONTEXT(ctx);
1111   enum mesa_debug_source source = gl_enum_to_debug_source(gl_source);
1112   enum mesa_debug_type type = gl_enum_to_debug_type(gl_type);
1113   enum mesa_debug_severity severity = gl_enum_to_debug_severity(gl_severity);
1114   const char *callerstr;
1115   struct gl_debug_state *debug;
1116
1117   if (_mesa_is_desktop_gl(ctx))
1118      callerstr = "glDebugMessageControl";
1119   else
1120      callerstr = "glDebugMessageControlKHR";
1121
1122   if (count < 0) {
1123      _mesa_error(ctx, GL_INVALID_VALUE,
1124                  "%s(count=%d : count must not be negative)", callerstr,
1125                  count);
1126      return;
1127   }
1128
1129   if (!validate_params(ctx, CONTROL, callerstr, gl_source, gl_type,
1130                        gl_severity))
1131      return; /* GL_INVALID_ENUM */
1132
1133   if (count && (gl_severity != GL_DONT_CARE || gl_type == GL_DONT_CARE
1134                 || gl_source == GL_DONT_CARE)) {
1135      _mesa_error(ctx, GL_INVALID_OPERATION,
1136                  "%s(When passing an array of ids, severity must be"
1137         " GL_DONT_CARE, and source and type must not be GL_DONT_CARE.",
1138                  callerstr);
1139      return;
1140   }
1141
1142   debug = _mesa_lock_debug_state(ctx);
1143   if (!debug)
1144      return;
1145
1146   if (count) {
1147      GLsizei i;
1148      for (i = 0; i < count; i++)
1149         debug_set_message_enable(debug, source, type, ids[i], enabled);
1150   }
1151   else {
1152      debug_set_message_enable_all(debug, source, type, severity, enabled);
1153   }
1154
1155   _mesa_unlock_debug_state(ctx);
1156}
1157
1158
1159void GLAPIENTRY
1160_mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam)
1161{
1162   GET_CURRENT_CONTEXT(ctx);
1163   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
1164   if (debug) {
1165      debug->Callback = callback;
1166      debug->CallbackData = userParam;
1167      _mesa_unlock_debug_state(ctx);
1168   }
1169}
1170
1171
1172void GLAPIENTRY
1173_mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
1174                     const GLchar *message)
1175{
1176   GET_CURRENT_CONTEXT(ctx);
1177   const char *callerstr;
1178   struct gl_debug_state *debug;
1179   struct gl_debug_message *emptySlot;
1180
1181   if (_mesa_is_desktop_gl(ctx))
1182      callerstr = "glPushDebugGroup";
1183   else
1184      callerstr = "glPushDebugGroupKHR";
1185
1186   switch(source) {
1187   case GL_DEBUG_SOURCE_APPLICATION:
1188   case GL_DEBUG_SOURCE_THIRD_PARTY:
1189      break;
1190   default:
1191      _mesa_error(ctx, GL_INVALID_ENUM, "bad value passed to %s"
1192                  "(source=0x%x)", callerstr, source);
1193      return;
1194   }
1195
1196   if (!validate_length(ctx, callerstr, length, message))
1197      return; /* GL_INVALID_VALUE */
1198
1199   if (length < 0)
1200      length = strlen(message);
1201
1202   debug = _mesa_lock_debug_state(ctx);
1203   if (!debug)
1204      return;
1205
1206   if (debug->CurrentGroup >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
1207      _mesa_unlock_debug_state(ctx);
1208      _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
1209      return;
1210   }
1211
1212   /* pop reuses the message details from push so we store this */
1213   emptySlot = debug_get_group_message(debug);
1214   debug_message_store(emptySlot,
1215                       gl_enum_to_debug_source(source),
1216                       gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP),
1217                       id,
1218                       gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
1219                       length, message);
1220
1221   debug_push_group(debug);
1222
1223   log_msg_locked_and_unlock(ctx,
1224         gl_enum_to_debug_source(source),
1225         MESA_DEBUG_TYPE_PUSH_GROUP, id,
1226         MESA_DEBUG_SEVERITY_NOTIFICATION, length,
1227         message);
1228}
1229
1230
1231void GLAPIENTRY
1232_mesa_PopDebugGroup(void)
1233{
1234   GET_CURRENT_CONTEXT(ctx);
1235   const char *callerstr;
1236   struct gl_debug_state *debug;
1237   struct gl_debug_message *gdmessage, msg;
1238
1239   if (_mesa_is_desktop_gl(ctx))
1240      callerstr = "glPopDebugGroup";
1241   else
1242      callerstr = "glPopDebugGroupKHR";
1243
1244   debug = _mesa_lock_debug_state(ctx);
1245   if (!debug)
1246      return;
1247
1248   if (debug->CurrentGroup <= 0) {
1249      _mesa_unlock_debug_state(ctx);
1250      _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr);
1251      return;
1252   }
1253
1254   debug_pop_group(debug);
1255
1256   /* make a shallow copy */
1257   gdmessage = debug_get_group_message(debug);
1258   msg = *gdmessage;
1259   gdmessage->message = NULL;
1260   gdmessage->length = 0;
1261
1262   log_msg_locked_and_unlock(ctx,
1263         msg.source,
1264         gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP),
1265         msg.id,
1266         gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
1267         msg.length, msg.message);
1268
1269   debug_message_clear(&msg);
1270}
1271
1272
1273void
1274_mesa_init_debug_output(struct gl_context *ctx)
1275{
1276   mtx_init(&ctx->DebugMutex, mtx_plain);
1277
1278   if (MESA_DEBUG_FLAGS & DEBUG_CONTEXT) {
1279      /* If the MESA_DEBUG env is set to "context", we'll turn on the
1280       * GL_CONTEXT_FLAG_DEBUG_BIT context flag and log debug output
1281       * messages to stderr (or whatever MESA_LOG_FILE points at).
1282       */
1283      struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
1284      if (!debug) {
1285         return;
1286      }
1287      debug->DebugOutput = GL_TRUE;
1288      debug->LogToStderr = GL_TRUE;
1289      ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
1290      _mesa_unlock_debug_state(ctx);
1291   }
1292}
1293
1294
1295void
1296_mesa_free_errors_data(struct gl_context *ctx)
1297{
1298   if (ctx->Debug) {
1299      debug_destroy(ctx->Debug);
1300      /* set to NULL just in case it is used before context is completely gone. */
1301      ctx->Debug = NULL;
1302   }
1303
1304   mtx_destroy(&ctx->DebugMutex);
1305}
1306
1307void GLAPIENTRY
1308_mesa_StringMarkerGREMEDY(GLsizei len, const GLvoid *string)
1309{
1310   GET_CURRENT_CONTEXT(ctx);
1311   if (ctx->Extensions.GREMEDY_string_marker) {
1312      /* if length not specified, string will be null terminated: */
1313      if (len <= 0)
1314         len = strlen(string);
1315      ctx->Driver.EmitStringMarker(ctx, string, len);
1316   } else {
1317      _mesa_error(ctx, GL_INVALID_OPERATION, "StringMarkerGREMEDY");
1318   }
1319}
1320