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