Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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