debug_output.c revision b8e80941
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 "enums.h"
31#include "imports.h"
32#include "hash.h"
33#include "mtypes.h"
34#include "version.h"
35#include "util/hash_table.h"
36#include "util/simple_list.h"
37
38
39static simple_mtx_t DynamicIDMutex = _SIMPLE_MTX_INITIALIZER_NP;
40static GLuint NextDynamicID = 1;
41
42
43/**
44 * A namespace element.
45 */
46struct gl_debug_element
47{
48   struct simple_node link;
49
50   GLuint ID;
51   /* at which severity levels (mesa_debug_severity) is the message enabled */
52   GLbitfield State;
53};
54
55
56struct gl_debug_namespace
57{
58   struct simple_node Elements;
59   GLbitfield DefaultState;
60};
61
62
63struct gl_debug_group {
64   struct gl_debug_namespace Namespaces[MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
65};
66
67
68/**
69 * An error, warning, or other piece of debug information for an application
70 * to consume via GL_ARB_debug_output/GL_KHR_debug.
71 */
72struct gl_debug_message
73{
74   enum mesa_debug_source source;
75   enum mesa_debug_type type;
76   GLuint id;
77   enum mesa_debug_severity severity;
78   /* length as given by the user - if message was explicitly null terminated,
79    * length can be negative */
80   GLsizei length;
81   GLcharARB *message;
82};
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
94
95struct gl_debug_state
96{
97   GLDEBUGPROC Callback;
98   const void *CallbackData;
99   GLboolean SyncOutput;
100   GLboolean DebugOutput;
101   GLboolean LogToStderr;
102
103   struct gl_debug_group *Groups[MAX_DEBUG_GROUP_STACK_DEPTH];
104   struct gl_debug_message GroupMessages[MAX_DEBUG_GROUP_STACK_DEPTH];
105   GLint CurrentGroup; // GroupStackDepth - 1
106
107   struct gl_debug_log Log;
108};
109
110
111static char out_of_memory[] = "Debugging error: out of memory";
112
113static const GLenum debug_source_enums[] = {
114   GL_DEBUG_SOURCE_API,
115   GL_DEBUG_SOURCE_WINDOW_SYSTEM,
116   GL_DEBUG_SOURCE_SHADER_COMPILER,
117   GL_DEBUG_SOURCE_THIRD_PARTY,
118   GL_DEBUG_SOURCE_APPLICATION,
119   GL_DEBUG_SOURCE_OTHER,
120};
121
122static const GLenum debug_type_enums[] = {
123   GL_DEBUG_TYPE_ERROR,
124   GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
125   GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
126   GL_DEBUG_TYPE_PORTABILITY,
127   GL_DEBUG_TYPE_PERFORMANCE,
128   GL_DEBUG_TYPE_OTHER,
129   GL_DEBUG_TYPE_MARKER,
130   GL_DEBUG_TYPE_PUSH_GROUP,
131   GL_DEBUG_TYPE_POP_GROUP,
132};
133
134static const GLenum debug_severity_enums[] = {
135   GL_DEBUG_SEVERITY_LOW,
136   GL_DEBUG_SEVERITY_MEDIUM,
137   GL_DEBUG_SEVERITY_HIGH,
138   GL_DEBUG_SEVERITY_NOTIFICATION,
139};
140
141
142static enum mesa_debug_source
143gl_enum_to_debug_source(GLenum e)
144{
145   unsigned i;
146
147   for (i = 0; i < ARRAY_SIZE(debug_source_enums); i++) {
148      if (debug_source_enums[i] == e)
149         break;
150   }
151   return i;
152}
153
154static enum mesa_debug_type
155gl_enum_to_debug_type(GLenum e)
156{
157   unsigned i;
158
159   for (i = 0; i < ARRAY_SIZE(debug_type_enums); i++) {
160      if (debug_type_enums[i] == e)
161         break;
162   }
163   return i;
164}
165
166static enum mesa_debug_severity
167gl_enum_to_debug_severity(GLenum e)
168{
169   unsigned i;
170
171   for (i = 0; i < ARRAY_SIZE(debug_severity_enums); i++) {
172      if (debug_severity_enums[i] == e)
173         break;
174   }
175   return i;
176}
177
178
179/**
180 * Handles generating a GL_ARB_debug_output message ID generated by the GL or
181 * GLSL compiler.
182 *
183 * The GL API has this "ID" mechanism, where the intention is to allow a
184 * client to filter in/out messages based on source, type, and ID.  Of course,
185 * building a giant enum list of all debug output messages that Mesa might
186 * generate is ridiculous, so instead we have our caller pass us a pointer to
187 * static storage where the ID should get stored.  This ID will be shared
188 * across all contexts for that message (which seems like a desirable
189 * property, even if it's not expected by the spec), but note that it won't be
190 * the same between executions if messages aren't generated in the same order.
191 */
192void
193_mesa_debug_get_id(GLuint *id)
194{
195   if (!(*id)) {
196      simple_mtx_lock(&DynamicIDMutex);
197      if (!(*id))
198         *id = NextDynamicID++;
199      simple_mtx_unlock(&DynamicIDMutex);
200   }
201}
202
203static void
204debug_message_clear(struct gl_debug_message *msg)
205{
206   if (msg->message != (char*)out_of_memory)
207      free(msg->message);
208   msg->message = NULL;
209   msg->length = 0;
210}
211
212static void
213debug_message_store(struct gl_debug_message *msg,
214                    enum mesa_debug_source source,
215                    enum mesa_debug_type type, GLuint id,
216                    enum mesa_debug_severity severity,
217                    GLsizei len, const char *buf)
218{
219   GLsizei length = len;
220
221   assert(!msg->message && !msg->length);
222
223   if (length < 0)
224      length = strlen(buf);
225
226   msg->message = malloc(length+1);
227   if (msg->message) {
228      (void) strncpy(msg->message, buf, (size_t)length);
229      msg->message[length] = '\0';
230
231      msg->length = len;
232      msg->source = source;
233      msg->type = type;
234      msg->id = id;
235      msg->severity = severity;
236   } else {
237      static GLuint oom_msg_id = 0;
238      _mesa_debug_get_id(&oom_msg_id);
239
240      /* malloc failed! */
241      msg->message = out_of_memory;
242      msg->length = -1;
243      msg->source = MESA_DEBUG_SOURCE_OTHER;
244      msg->type = MESA_DEBUG_TYPE_ERROR;
245      msg->id = oom_msg_id;
246      msg->severity = MESA_DEBUG_SEVERITY_HIGH;
247   }
248}
249
250static void
251debug_namespace_init(struct gl_debug_namespace *ns)
252{
253   make_empty_list(&ns->Elements);
254
255   /* Enable all the messages with severity HIGH or MEDIUM by default */
256   ns->DefaultState = (1 << MESA_DEBUG_SEVERITY_MEDIUM ) |
257                      (1 << MESA_DEBUG_SEVERITY_HIGH) |
258                      (1 << MESA_DEBUG_SEVERITY_NOTIFICATION);
259}
260
261static void
262debug_namespace_clear(struct gl_debug_namespace *ns)
263{
264   struct simple_node *node, *tmp;
265
266   foreach_s(node, tmp, &ns->Elements)
267      free(node);
268}
269
270static bool
271debug_namespace_copy(struct gl_debug_namespace *dst,
272                     const struct gl_debug_namespace *src)
273{
274   struct simple_node *node;
275
276   dst->DefaultState = src->DefaultState;
277
278   make_empty_list(&dst->Elements);
279   foreach(node, &src->Elements) {
280      const struct gl_debug_element *elem =
281         (const struct gl_debug_element *) node;
282      struct gl_debug_element *copy;
283
284      copy = malloc(sizeof(*copy));
285      if (!copy) {
286         debug_namespace_clear(dst);
287         return false;
288      }
289
290      copy->ID = elem->ID;
291      copy->State = elem->State;
292      insert_at_tail(&dst->Elements, &copy->link);
293   }
294
295   return true;
296}
297
298/**
299 * Set the state of \p id in the namespace.
300 */
301static bool
302debug_namespace_set(struct gl_debug_namespace *ns,
303                    GLuint id, bool enabled)
304{
305   const uint32_t state = (enabled) ?
306      ((1 << MESA_DEBUG_SEVERITY_COUNT) - 1) : 0;
307   struct gl_debug_element *elem = NULL;
308   struct simple_node *node;
309
310   /* find the element */
311   foreach(node, &ns->Elements) {
312      struct gl_debug_element *tmp = (struct gl_debug_element *) node;
313      if (tmp->ID == id) {
314         elem = tmp;
315         break;
316      }
317   }
318
319   /* we do not need the element if it has the default state */
320   if (ns->DefaultState == state) {
321      if (elem) {
322         remove_from_list(&elem->link);
323         free(elem);
324      }
325      return true;
326   }
327
328   if (!elem) {
329      elem = malloc(sizeof(*elem));
330      if (!elem)
331         return false;
332
333      elem->ID = id;
334      insert_at_tail(&ns->Elements, &elem->link);
335   }
336
337   elem->State = state;
338
339   return true;
340}
341
342/**
343 * Set the default state of the namespace for \p severity.  When \p severity
344 * is MESA_DEBUG_SEVERITY_COUNT, the default values for all severities are
345 * updated.
346 */
347static void
348debug_namespace_set_all(struct gl_debug_namespace *ns,
349                        enum mesa_debug_severity severity,
350                        bool enabled)
351{
352   struct simple_node *node, *tmp;
353   uint32_t mask, val;
354
355   /* set all elements to the same state */
356   if (severity == MESA_DEBUG_SEVERITY_COUNT) {
357      ns->DefaultState = (enabled) ? ((1 << severity) - 1) : 0;
358      debug_namespace_clear(ns);
359      make_empty_list(&ns->Elements);
360      return;
361   }
362
363   mask = 1 << severity;
364   val = (enabled) ? mask : 0;
365
366   ns->DefaultState = (ns->DefaultState & ~mask) | val;
367
368   foreach_s(node, tmp, &ns->Elements) {
369      struct gl_debug_element *elem = (struct gl_debug_element *) node;
370
371      elem->State = (elem->State & ~mask) | val;
372      if (elem->State == ns->DefaultState) {
373         remove_from_list(node);
374         free(node);
375      }
376   }
377}
378
379/**
380 * Get the state of \p id in the namespace.
381 */
382static bool
383debug_namespace_get(const struct gl_debug_namespace *ns, GLuint id,
384                    enum mesa_debug_severity severity)
385{
386   struct simple_node *node;
387   uint32_t state;
388
389   state = ns->DefaultState;
390   foreach(node, &ns->Elements) {
391      struct gl_debug_element *elem = (struct gl_debug_element *) node;
392
393      if (elem->ID == id) {
394         state = elem->State;
395         break;
396      }
397   }
398
399   return (state & (1 << severity));
400}
401
402/**
403 * Allocate and initialize context debug state.
404 */
405static struct gl_debug_state *
406debug_create(void)
407{
408   struct gl_debug_state *debug;
409   int s, t;
410
411   debug = CALLOC_STRUCT(gl_debug_state);
412   if (!debug)
413      return NULL;
414
415   debug->Groups[0] = malloc(sizeof(*debug->Groups[0]));
416   if (!debug->Groups[0]) {
417      free(debug);
418      return NULL;
419   }
420
421   /* Initialize state for filtering known debug messages. */
422   for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
423      for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
424         debug_namespace_init(&debug->Groups[0]->Namespaces[s][t]);
425   }
426
427   return debug;
428}
429
430/**
431 * Return true if the top debug group points to the group below it.
432 */
433static bool
434debug_is_group_read_only(const struct gl_debug_state *debug)
435{
436   const GLint gstack = debug->CurrentGroup;
437   return (gstack > 0 && debug->Groups[gstack] == debug->Groups[gstack - 1]);
438}
439
440/**
441 * Make the top debug group writable.
442 */
443static bool
444debug_make_group_writable(struct gl_debug_state *debug)
445{
446   const GLint gstack = debug->CurrentGroup;
447   const struct gl_debug_group *src = debug->Groups[gstack];
448   struct gl_debug_group *dst;
449   int s, t;
450
451   if (!debug_is_group_read_only(debug))
452      return true;
453
454   dst = malloc(sizeof(*dst));
455   if (!dst)
456      return false;
457
458   for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
459      for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
460         if (!debug_namespace_copy(&dst->Namespaces[s][t],
461                                   &src->Namespaces[s][t])) {
462            /* error path! */
463            for (t = t - 1; t >= 0; t--)
464               debug_namespace_clear(&dst->Namespaces[s][t]);
465            for (s = s - 1; s >= 0; s--) {
466               for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
467                  debug_namespace_clear(&dst->Namespaces[s][t]);
468            }
469            free(dst);
470            return false;
471         }
472      }
473   }
474
475   debug->Groups[gstack] = dst;
476
477   return true;
478}
479
480/**
481 * Free the top debug group.
482 */
483static void
484debug_clear_group(struct gl_debug_state *debug)
485{
486   const GLint gstack = debug->CurrentGroup;
487
488   if (!debug_is_group_read_only(debug)) {
489      struct gl_debug_group *grp = debug->Groups[gstack];
490      int s, t;
491
492      for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
493         for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++)
494            debug_namespace_clear(&grp->Namespaces[s][t]);
495      }
496
497      free(grp);
498   }
499
500   debug->Groups[gstack] = NULL;
501}
502
503/**
504 * Delete the oldest debug messages out of the log.
505 */
506static void
507debug_delete_messages(struct gl_debug_state *debug, int count)
508{
509   struct gl_debug_log *log = &debug->Log;
510
511   if (count > log->NumMessages)
512      count = log->NumMessages;
513
514   while (count--) {
515      struct gl_debug_message *msg = &log->Messages[log->NextMessage];
516
517      debug_message_clear(msg);
518
519      log->NumMessages--;
520      log->NextMessage++;
521      log->NextMessage %= MAX_DEBUG_LOGGED_MESSAGES;
522   }
523}
524
525/**
526 * Loop through debug group stack tearing down states for
527 * filtering debug messages.  Then free debug output state.
528 */
529static void
530debug_destroy(struct gl_debug_state *debug)
531{
532   while (debug->CurrentGroup > 0) {
533      debug_clear_group(debug);
534      debug->CurrentGroup--;
535   }
536
537   debug_clear_group(debug);
538   debug_delete_messages(debug, debug->Log.NumMessages);
539   free(debug);
540}
541
542/**
543 * Sets the state of the given message source/type/ID tuple.
544 */
545static void
546debug_set_message_enable(struct gl_debug_state *debug,
547                         enum mesa_debug_source source,
548                         enum mesa_debug_type type,
549                         GLuint id, GLboolean enabled)
550{
551   const GLint gstack = debug->CurrentGroup;
552   struct gl_debug_namespace *ns;
553
554   debug_make_group_writable(debug);
555   ns = &debug->Groups[gstack]->Namespaces[source][type];
556
557   debug_namespace_set(ns, id, enabled);
558}
559
560/*
561 * Set the state of all message IDs found in the given intersection of
562 * 'source', 'type', and 'severity'.  The _COUNT enum can be used for
563 * GL_DONT_CARE (include all messages in the class).
564 *
565 * This requires both setting the state of all previously seen message
566 * IDs in the hash table, and setting the default state for all
567 * applicable combinations of source/type/severity, so that all the
568 * yet-unknown message IDs that may be used in the future will be
569 * impacted as if they were already known.
570 */
571static void
572debug_set_message_enable_all(struct gl_debug_state *debug,
573                             enum mesa_debug_source source,
574                             enum mesa_debug_type type,
575                             enum mesa_debug_severity severity,
576                             GLboolean enabled)
577{
578   const GLint gstack = debug->CurrentGroup;
579   int s, t, smax, tmax;
580
581   if (source == MESA_DEBUG_SOURCE_COUNT) {
582      source = 0;
583      smax = MESA_DEBUG_SOURCE_COUNT;
584   } else {
585      smax = source+1;
586   }
587
588   if (type == MESA_DEBUG_TYPE_COUNT) {
589      type = 0;
590      tmax = MESA_DEBUG_TYPE_COUNT;
591   } else {
592      tmax = type+1;
593   }
594
595   debug_make_group_writable(debug);
596
597   for (s = source; s < smax; s++) {
598      for (t = type; t < tmax; t++) {
599         struct gl_debug_namespace *nspace =
600            &debug->Groups[gstack]->Namespaces[s][t];
601         debug_namespace_set_all(nspace, severity, enabled);
602      }
603   }
604}
605
606/**
607 * Returns if the given message source/type/ID tuple is enabled.
608 */
609bool
610_mesa_debug_is_message_enabled(const struct gl_debug_state *debug,
611                               enum mesa_debug_source source,
612                               enum mesa_debug_type type,
613                               GLuint id,
614                               enum mesa_debug_severity severity)
615{
616   const GLint gstack = debug->CurrentGroup;
617   struct gl_debug_group *grp = debug->Groups[gstack];
618   struct gl_debug_namespace *nspace = &grp->Namespaces[source][type];
619
620   if (!debug->DebugOutput)
621      return false;
622
623   return debug_namespace_get(nspace, id, severity);
624}
625
626/**
627 * 'buf' is not necessarily a null-terminated string. When logging, copy
628 * 'len' characters from it, store them in a new, null-terminated string,
629 * and remember the number of bytes used by that string, *including*
630 * the null terminator this time.
631 */
632static void
633debug_log_message(struct gl_debug_state *debug,
634                  enum mesa_debug_source source,
635                  enum mesa_debug_type type, GLuint id,
636                  enum mesa_debug_severity severity,
637                  GLsizei len, const char *buf)
638{
639   struct gl_debug_log *log = &debug->Log;
640   GLint nextEmpty;
641   struct gl_debug_message *emptySlot;
642
643   if (debug->LogToStderr) {
644      _mesa_log("Mesa debug output: %.*s\n", len, buf);
645   }
646
647   assert(len < MAX_DEBUG_MESSAGE_LENGTH);
648
649   if (log->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
650      return;
651
652   nextEmpty = (log->NextMessage + log->NumMessages)
653      % MAX_DEBUG_LOGGED_MESSAGES;
654   emptySlot = &log->Messages[nextEmpty];
655
656   debug_message_store(emptySlot, source, type,
657                       id, severity, len, buf);
658
659   log->NumMessages++;
660}
661
662/**
663 * Return the oldest debug message out of the log.
664 */
665static const struct gl_debug_message *
666debug_fetch_message(const struct gl_debug_state *debug)
667{
668   const struct gl_debug_log *log = &debug->Log;
669
670   return (log->NumMessages) ? &log->Messages[log->NextMessage] : NULL;
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   simple_mtx_lock(&ctx->DebugMutex);
706
707   if (!ctx->Debug) {
708      ctx->Debug = debug_create();
709      if (!ctx->Debug) {
710         GET_CURRENT_CONTEXT(cur);
711         simple_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   simple_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   simple_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   simple_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