mesa: refactor debug output control_messages
[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 "errors.h"
32 #include "enums.h"
33 #include "imports.h"
34 #include "context.h"
35 #include "dispatch.h"
36 #include "hash.h"
37 #include "mtypes.h"
38 #include "version.h"
39 #include "hash_table.h"
40
41 static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP;
42 static GLuint NextDynamicID = 1;
43
44 struct gl_debug_severity
45 {
46 struct simple_node link;
47 GLuint ID;
48 };
49
50 static char out_of_memory[] = "Debugging error: out of memory";
51
52 static const GLenum debug_source_enums[] = {
53 GL_DEBUG_SOURCE_API,
54 GL_DEBUG_SOURCE_WINDOW_SYSTEM,
55 GL_DEBUG_SOURCE_SHADER_COMPILER,
56 GL_DEBUG_SOURCE_THIRD_PARTY,
57 GL_DEBUG_SOURCE_APPLICATION,
58 GL_DEBUG_SOURCE_OTHER,
59 };
60
61 static const GLenum debug_type_enums[] = {
62 GL_DEBUG_TYPE_ERROR,
63 GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
64 GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
65 GL_DEBUG_TYPE_PORTABILITY,
66 GL_DEBUG_TYPE_PERFORMANCE,
67 GL_DEBUG_TYPE_OTHER,
68 GL_DEBUG_TYPE_MARKER,
69 GL_DEBUG_TYPE_PUSH_GROUP,
70 GL_DEBUG_TYPE_POP_GROUP,
71 };
72
73 static const GLenum debug_severity_enums[] = {
74 GL_DEBUG_SEVERITY_LOW,
75 GL_DEBUG_SEVERITY_MEDIUM,
76 GL_DEBUG_SEVERITY_HIGH,
77 GL_DEBUG_SEVERITY_NOTIFICATION,
78 };
79
80
81 static enum mesa_debug_source
82 gl_enum_to_debug_source(GLenum e)
83 {
84 int i;
85
86 for (i = 0; i < Elements(debug_source_enums); i++) {
87 if (debug_source_enums[i] == e)
88 break;
89 }
90 return i;
91 }
92
93 static enum mesa_debug_type
94 gl_enum_to_debug_type(GLenum e)
95 {
96 int i;
97
98 for (i = 0; i < Elements(debug_type_enums); i++) {
99 if (debug_type_enums[i] == e)
100 break;
101 }
102 return i;
103 }
104
105 static enum mesa_debug_severity
106 gl_enum_to_debug_severity(GLenum e)
107 {
108 int i;
109
110 for (i = 0; i < Elements(debug_severity_enums); i++) {
111 if (debug_severity_enums[i] == e)
112 break;
113 }
114 return i;
115 }
116
117
118 /**
119 * Handles generating a GL_ARB_debug_output message ID generated by the GL or
120 * GLSL compiler.
121 *
122 * The GL API has this "ID" mechanism, where the intention is to allow a
123 * client to filter in/out messages based on source, type, and ID. Of course,
124 * building a giant enum list of all debug output messages that Mesa might
125 * generate is ridiculous, so instead we have our caller pass us a pointer to
126 * static storage where the ID should get stored. This ID will be shared
127 * across all contexts for that message (which seems like a desirable
128 * property, even if it's not expected by the spec), but note that it won't be
129 * the same between executions if messages aren't generated in the same order.
130 */
131 static void
132 debug_get_id(GLuint *id)
133 {
134 if (!(*id)) {
135 mtx_lock(&DynamicIDMutex);
136 if (!(*id))
137 *id = NextDynamicID++;
138 mtx_unlock(&DynamicIDMutex);
139 }
140 }
141
142
143 /*
144 * We store a bitfield in the hash table, with five possible values total.
145 *
146 * The ENABLED_BIT's purpose is self-explanatory.
147 *
148 * The FOUND_BIT is needed to differentiate the value of DISABLED from
149 * the value returned by HashTableLookup() when it can't find the given key.
150 *
151 * The KNOWN_SEVERITY bit is a bit complicated:
152 *
153 * A client may call Control() with an array of IDs, then call Control()
154 * on all message IDs of a certain severity, then Insert() one of the
155 * previously specified IDs, giving us a known severity level, then call
156 * Control() on all message IDs of a certain severity level again.
157 *
158 * After the first call, those IDs will have a FOUND_BIT, but will not
159 * exist in any severity-specific list, so the second call will not
160 * impact them. This is undesirable but unavoidable given the API:
161 * The only entrypoint that gives a severity for a client-defined ID
162 * is the Insert() call.
163 *
164 * For the sake of Control(), we want to maintain the invariant
165 * that an ID will either appear in none of the three severity lists,
166 * or appear once, to minimize pointless duplication and potential surprises.
167 *
168 * Because Insert() is the only place that will learn an ID's severity,
169 * it should insert an ID into the appropriate list, but only if the ID
170 * doesn't exist in it or any other list yet. Because searching all three
171 * lists at O(n) is needlessly expensive, we store KNOWN_SEVERITY.
172 */
173 enum {
174 FOUND_BIT = 1 << 0,
175 ENABLED_BIT = 1 << 1,
176 KNOWN_SEVERITY = 1 << 2,
177
178 /* HashTable reserves zero as a return value meaning 'not found' */
179 NOT_FOUND = 0,
180 DISABLED = FOUND_BIT,
181 ENABLED = ENABLED_BIT | FOUND_BIT
182 };
183
184 static void
185 debug_message_clear(struct gl_debug_msg *msg)
186 {
187 if (msg->message != (char*)out_of_memory)
188 free(msg->message);
189 msg->message = NULL;
190 msg->length = 0;
191 }
192
193 static void
194 debug_message_store(struct gl_debug_msg *msg,
195 enum mesa_debug_source source,
196 enum mesa_debug_type type, GLuint id,
197 enum mesa_debug_severity severity,
198 GLsizei len, const char *buf)
199 {
200 assert(!msg->message && !msg->length);
201
202 msg->message = malloc(len+1);
203 if (msg->message) {
204 (void) strncpy(msg->message, buf, (size_t)len);
205 msg->message[len] = '\0';
206
207 msg->length = len+1;
208 msg->source = source;
209 msg->type = type;
210 msg->id = id;
211 msg->severity = severity;
212 } else {
213 static GLuint oom_msg_id = 0;
214 debug_get_id(&oom_msg_id);
215
216 /* malloc failed! */
217 msg->message = out_of_memory;
218 msg->length = strlen(out_of_memory)+1;
219 msg->source = MESA_DEBUG_SOURCE_OTHER;
220 msg->type = MESA_DEBUG_TYPE_ERROR;
221 msg->id = oom_msg_id;
222 msg->severity = MESA_DEBUG_SEVERITY_HIGH;
223 }
224 }
225
226 /**
227 * Allocate and initialize context debug state.
228 */
229 static struct gl_debug_state *
230 debug_create(void)
231 {
232 struct gl_debug_state *debug;
233 int s, t, sev;
234
235 debug = CALLOC_STRUCT(gl_debug_state);
236 if (!debug)
237 return NULL;
238
239 /* Enable all the messages with severity HIGH or MEDIUM by default. */
240 memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE,
241 sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH]);
242 memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE,
243 sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]);
244 memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE,
245 sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW]);
246
247 /* Initialize state for filtering known debug messages. */
248 for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
249 for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
250 debug->Namespaces[0][s][t].IDs = _mesa_NewHashTable();
251 assert(debug->Namespaces[0][s][t].IDs);
252
253 for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
254 make_empty_list(&debug->Namespaces[0][s][t].Severity[sev]);
255 }
256 }
257 }
258
259 return debug;
260 }
261
262 /*
263 * Sets the state of the given message source/type/ID tuple.
264 */
265 static void
266 debug_set_message_enable(struct gl_debug_state *debug,
267 enum mesa_debug_source source,
268 enum mesa_debug_type type,
269 GLuint id, GLboolean enabled)
270 {
271 GLint gstack = debug->GroupStackDepth;
272 struct gl_debug_namespace *nspace =
273 &debug->Namespaces[gstack][source][type];
274 uintptr_t state;
275
276 /* In addition to not being able to store zero as a value, HashTable also
277 * can't use zero as a key.
278 */
279 if (id)
280 state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
281 else
282 state = nspace->ZeroID;
283
284 if (state == NOT_FOUND)
285 state = enabled ? ENABLED : DISABLED;
286 else {
287 if (enabled)
288 state |= ENABLED_BIT;
289 else
290 state &= ~ENABLED_BIT;
291 }
292
293 if (id)
294 _mesa_HashInsert(nspace->IDs, id, (void*)state);
295 else
296 nspace->ZeroID = state;
297 }
298
299 /*
300 * Set the state of all message IDs found in the given intersection of
301 * 'source', 'type', and 'severity'. The _COUNT enum can be used for
302 * GL_DONT_CARE (include all messages in the class).
303 *
304 * This requires both setting the state of all previously seen message
305 * IDs in the hash table, and setting the default state for all
306 * applicable combinations of source/type/severity, so that all the
307 * yet-unknown message IDs that may be used in the future will be
308 * impacted as if they were already known.
309 */
310 static void
311 debug_set_message_enable_all(struct gl_debug_state *debug,
312 enum mesa_debug_source source,
313 enum mesa_debug_type type,
314 enum mesa_debug_severity severity,
315 GLboolean enabled)
316 {
317 const GLint gstack = debug->GroupStackDepth;
318 int s, t, sev, smax, tmax, sevmax;
319
320 if (source == MESA_DEBUG_SOURCE_COUNT) {
321 source = 0;
322 smax = MESA_DEBUG_SOURCE_COUNT;
323 } else {
324 smax = source+1;
325 }
326
327 if (type == MESA_DEBUG_TYPE_COUNT) {
328 type = 0;
329 tmax = MESA_DEBUG_TYPE_COUNT;
330 } else {
331 tmax = type+1;
332 }
333
334 if (severity == MESA_DEBUG_SEVERITY_COUNT) {
335 severity = 0;
336 sevmax = MESA_DEBUG_SEVERITY_COUNT;
337 } else {
338 sevmax = severity+1;
339 }
340
341 for (sev = severity; sev < sevmax; sev++) {
342 for (s = source; s < smax; s++) {
343 for (t = type; t < tmax; t++) {
344 struct simple_node *node;
345 struct gl_debug_severity *entry;
346
347 /* change the default for IDs we've never seen before. */
348 debug->Defaults[gstack][sev][s][t] = enabled;
349
350 /* Now change the state of IDs we *have* seen... */
351 foreach(node, &debug->Namespaces[gstack][s][t].Severity[sev]) {
352 entry = (struct gl_debug_severity *)node;
353 debug_set_message_enable(debug, s, t, entry->ID, enabled);
354 }
355 }
356 }
357 }
358 }
359
360 /**
361 * Returns if the given message source/type/ID tuple is enabled.
362 */
363 static bool
364 debug_is_message_enabled(struct gl_debug_state *debug,
365 enum mesa_debug_source source,
366 enum mesa_debug_type type,
367 GLuint id,
368 enum mesa_debug_severity severity)
369 {
370 const GLint gstack = debug->GroupStackDepth;
371 struct gl_debug_namespace *nspace =
372 &debug->Namespaces[gstack][source][type];
373 uintptr_t state = 0;
374
375 if (!debug->DebugOutput)
376 return false;
377
378 /* In addition to not being able to store zero as a value, HashTable also
379 * can't use zero as a key.
380 */
381 if (id)
382 state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
383 else
384 state = nspace->ZeroID;
385
386 /* Only do this once for each ID. This makes sure the ID exists in,
387 * at most, one list, and does not pointlessly appear multiple times.
388 */
389 if (!(state & KNOWN_SEVERITY)) {
390 struct gl_debug_severity *entry;
391
392 if (state == NOT_FOUND) {
393 if (debug->Defaults[gstack][severity][source][type])
394 state = ENABLED;
395 else
396 state = DISABLED;
397 }
398
399 entry = malloc(sizeof *entry);
400 if (!entry)
401 goto out;
402
403 state |= KNOWN_SEVERITY;
404
405 if (id)
406 _mesa_HashInsert(nspace->IDs, id, (void*)state);
407 else
408 nspace->ZeroID = state;
409
410 entry->ID = id;
411 insert_at_tail(&nspace->Severity[severity], &entry->link);
412 }
413 out:
414 return (state & ENABLED_BIT);
415 }
416
417 /**
418 * 'buf' is not necessarily a null-terminated string. When logging, copy
419 * 'len' characters from it, store them in a new, null-terminated string,
420 * and remember the number of bytes used by that string, *including*
421 * the null terminator this time.
422 */
423 static void
424 debug_log_message(struct gl_debug_state *debug,
425 enum mesa_debug_source source,
426 enum mesa_debug_type type, GLuint id,
427 enum mesa_debug_severity severity,
428 GLsizei len, const char *buf)
429 {
430 GLint nextEmpty;
431 struct gl_debug_msg *emptySlot;
432
433 assert(len >= 0 && len < MAX_DEBUG_MESSAGE_LENGTH);
434
435 if (debug->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
436 return;
437
438 nextEmpty = (debug->NextMsg + debug->NumMessages)
439 % MAX_DEBUG_LOGGED_MESSAGES;
440 emptySlot = &debug->Log[nextEmpty];
441
442 debug_message_store(emptySlot, source, type,
443 id, severity, len, buf);
444
445 if (debug->NumMessages == 0)
446 debug->NextMsgLength = debug->Log[debug->NextMsg].length;
447
448 debug->NumMessages++;
449 }
450
451 /**
452 * Return the oldest debug message out of the log.
453 */
454 static const struct gl_debug_msg *
455 debug_fetch_message(const struct gl_debug_state *debug)
456 {
457 return (debug->NumMessages) ? &debug->Log[debug->NextMsg] : NULL;
458 }
459
460 /**
461 * Delete the oldest debug messages out of the log.
462 */
463 static void
464 debug_delete_messages(struct gl_debug_state *debug, unsigned count)
465 {
466 if (count > debug->NumMessages)
467 count = debug->NumMessages;
468
469 while (count--) {
470 struct gl_debug_msg *msg = &debug->Log[debug->NextMsg];
471
472 assert(msg->length > 0 && msg->length == debug->NextMsgLength);
473 debug_message_clear(msg);
474
475 debug->NumMessages--;
476 debug->NextMsg++;
477 debug->NextMsg %= MAX_DEBUG_LOGGED_MESSAGES;
478 debug->NextMsgLength = debug->Log[debug->NextMsg].length;
479 }
480 }
481
482
483 /**
484 * Return debug state for the context. The debug state will be allocated
485 * and initialized upon the first call.
486 */
487 struct gl_debug_state *
488 _mesa_get_debug_state(struct gl_context *ctx)
489 {
490 if (!ctx->Debug) {
491 ctx->Debug = debug_create();
492 if (!ctx->Debug) {
493 _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
494 }
495 }
496
497 return ctx->Debug;
498 }
499
500
501
502 static GLboolean
503 should_log(struct gl_context *ctx,
504 enum mesa_debug_source source,
505 enum mesa_debug_type type,
506 GLuint id,
507 enum mesa_debug_severity severity)
508 {
509 struct gl_debug_state *debug;
510
511 if (!ctx->Debug) {
512 /* no debug state set so far */
513 return GL_FALSE;
514 }
515
516 debug = _mesa_get_debug_state(ctx);
517 if (debug)
518 return debug_is_message_enabled(debug, source, type, id, severity);
519 else
520 return GL_FALSE;
521 }
522
523
524 static void
525 set_message_state(struct gl_context *ctx,
526 enum mesa_debug_source source,
527 enum mesa_debug_type type,
528 GLuint id, GLboolean enabled)
529 {
530 struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
531
532 if (debug)
533 debug_set_message_enable(debug, source, type, id, enabled);
534 }
535
536
537
538 /**
539 * Log a client or driver debug message.
540 */
541 static void
542 log_msg(struct gl_context *ctx, enum mesa_debug_source source,
543 enum mesa_debug_type type, GLuint id,
544 enum mesa_debug_severity severity, GLint len, const char *buf)
545 {
546 struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
547
548 if (!debug)
549 return;
550
551 if (!should_log(ctx, source, type, id, severity))
552 return;
553
554 if (debug->Callback) {
555 GLenum gl_type = debug_type_enums[type];
556 GLenum gl_severity = debug_severity_enums[severity];
557
558 debug->Callback(debug_source_enums[source], gl_type, id, gl_severity,
559 len, buf, debug->CallbackData);
560 return;
561 }
562
563 debug_log_message(debug, source, type, id, severity, len, buf);
564 }
565
566
567 /**
568 * Pop the oldest debug message out of the log.
569 * Writes the message string, including the null terminator, into 'buf',
570 * using up to 'bufSize' bytes. If 'bufSize' is too small, or
571 * if 'buf' is NULL, nothing is written.
572 *
573 * Returns the number of bytes written on success, or when 'buf' is NULL,
574 * the number that would have been written. A return value of 0
575 * indicates failure.
576 */
577 static GLsizei
578 get_msg(struct gl_context *ctx, GLenum *source, GLenum *type,
579 GLuint *id, GLenum *severity, GLsizei bufSize, char *buf)
580 {
581 struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
582 const struct gl_debug_msg *msg;
583 GLsizei length;
584
585 if (!debug)
586 return 0;
587
588 msg = debug_fetch_message(debug);
589 if (!msg)
590 return 0;
591
592 msg = &debug->Log[debug->NextMsg];
593 length = msg->length;
594
595 assert(length > 0 && length == debug->NextMsgLength);
596
597 if (bufSize < length && buf != NULL)
598 return 0;
599
600 if (severity) {
601 *severity = debug_severity_enums[msg->severity];
602 }
603
604 if (source) {
605 *source = debug_source_enums[msg->source];
606 }
607
608 if (type) {
609 *type = debug_type_enums[msg->type];
610 }
611
612 if (id) {
613 *id = msg->id;
614 }
615
616 if (buf) {
617 assert(msg->message[length-1] == '\0');
618 (void) strncpy(buf, msg->message, (size_t)length);
619 }
620
621 debug_delete_messages(debug, 1);
622
623 return length;
624 }
625
626
627 /**
628 * Verify that source, type, and severity are valid enums.
629 *
630 * The 'caller' param is used for handling values available
631 * only in glDebugMessageInsert or glDebugMessageControl
632 */
633 static GLboolean
634 validate_params(struct gl_context *ctx, unsigned caller,
635 const char *callerstr, GLenum source, GLenum type,
636 GLenum severity)
637 {
638 #define INSERT 1
639 #define CONTROL 2
640 switch(source) {
641 case GL_DEBUG_SOURCE_APPLICATION_ARB:
642 case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
643 break;
644 case GL_DEBUG_SOURCE_API_ARB:
645 case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
646 case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
647 case GL_DEBUG_SOURCE_OTHER_ARB:
648 if (caller != INSERT)
649 break;
650 else
651 goto error;
652 case GL_DONT_CARE:
653 if (caller == CONTROL)
654 break;
655 else
656 goto error;
657 default:
658 goto error;
659 }
660
661 switch(type) {
662 case GL_DEBUG_TYPE_ERROR_ARB:
663 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
664 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
665 case GL_DEBUG_TYPE_PERFORMANCE_ARB:
666 case GL_DEBUG_TYPE_PORTABILITY_ARB:
667 case GL_DEBUG_TYPE_OTHER_ARB:
668 case GL_DEBUG_TYPE_MARKER:
669 break;
670 case GL_DEBUG_TYPE_PUSH_GROUP:
671 case GL_DEBUG_TYPE_POP_GROUP:
672 case GL_DONT_CARE:
673 if (caller == CONTROL)
674 break;
675 else
676 goto error;
677 default:
678 goto error;
679 }
680
681 switch(severity) {
682 case GL_DEBUG_SEVERITY_HIGH_ARB:
683 case GL_DEBUG_SEVERITY_MEDIUM_ARB:
684 case GL_DEBUG_SEVERITY_LOW_ARB:
685 case GL_DEBUG_SEVERITY_NOTIFICATION:
686 break;
687 case GL_DONT_CARE:
688 if (caller == CONTROL)
689 break;
690 else
691 goto error;
692 default:
693 goto error;
694 }
695 return GL_TRUE;
696
697 error:
698 _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s"
699 "(source=0x%x, type=0x%x, severity=0x%x)", callerstr,
700 source, type, severity);
701
702 return GL_FALSE;
703 }
704
705
706 static void
707 control_messages(struct gl_context *ctx,
708 enum mesa_debug_source source,
709 enum mesa_debug_type type,
710 enum mesa_debug_severity severity,
711 GLboolean enabled)
712 {
713 struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
714
715 if (!debug)
716 return;
717
718 debug_set_message_enable_all(debug, source, type, severity, enabled);
719 }
720
721
722 /**
723 * Debugging-message namespaces with the source APPLICATION or THIRD_PARTY
724 * require special handling, since the IDs in them are controlled by clients,
725 * not the OpenGL implementation.
726 *
727 * 'count' is the length of the array 'ids'. If 'count' is nonzero, all
728 * the given IDs in the namespace defined by 'esource' and 'etype'
729 * will be affected.
730 *
731 * If 'count' is zero, this sets the state of all IDs that match
732 * the combination of 'esource', 'etype', and 'eseverity'.
733 */
734 static void
735 control_app_messages(struct gl_context *ctx, GLenum esource, GLenum etype,
736 GLenum eseverity, GLsizei count, const GLuint *ids,
737 GLboolean enabled)
738 {
739 GLsizei i;
740 enum mesa_debug_source source = gl_enum_to_debug_source(esource);
741 enum mesa_debug_type type = gl_enum_to_debug_type(etype);
742 enum mesa_debug_severity severity = gl_enum_to_debug_severity(eseverity);
743
744 for (i = 0; i < count; i++)
745 set_message_state(ctx, source, type, ids[i], enabled);
746
747 if (count)
748 return;
749
750 control_messages(ctx, source, type, severity, enabled);
751 }
752
753
754 /**
755 * This is a generic message insert function.
756 * Validation of source, type and severity parameters should be done
757 * before calling this funtion.
758 */
759 static void
760 message_insert(GLenum source, GLenum type, GLuint id,
761 GLenum severity, GLint length, const GLchar *buf,
762 const char *callerstr)
763 {
764 GET_CURRENT_CONTEXT(ctx);
765
766 if (length < 0)
767 length = strlen(buf);
768
769 if (length >= MAX_DEBUG_MESSAGE_LENGTH) {
770 _mesa_error(ctx, GL_INVALID_VALUE,
771 "%s(length=%d, which is not less than "
772 "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, length,
773 MAX_DEBUG_MESSAGE_LENGTH);
774 return;
775 }
776
777 log_msg(ctx,
778 gl_enum_to_debug_source(source),
779 gl_enum_to_debug_type(type), id,
780 gl_enum_to_debug_severity(severity), length, buf);
781 }
782
783
784 static void
785 do_nothing(GLuint key, void *data, void *userData)
786 {
787 }
788
789
790 /**
791 * Free context state pertaining to error/debug state for the given stack
792 * depth.
793 */
794 static void
795 free_errors_data(struct gl_context *ctx, GLint gstack)
796 {
797 struct gl_debug_state *debug = ctx->Debug;
798 enum mesa_debug_type t;
799 enum mesa_debug_source s;
800 enum mesa_debug_severity sev;
801
802 assert(debug);
803
804 /* Tear down state for filtering debug messages. */
805 for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
806 for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
807 _mesa_HashDeleteAll(debug->Namespaces[gstack][s][t].IDs,
808 do_nothing, NULL);
809 _mesa_DeleteHashTable(debug->Namespaces[gstack][s][t].IDs);
810 for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
811 struct simple_node *node, *tmp;
812 struct gl_debug_severity *entry;
813
814 foreach_s(node, tmp,
815 &debug->Namespaces[gstack][s][t].Severity[sev]) {
816 entry = (struct gl_debug_severity *)node;
817 free(entry);
818 }
819 }
820 }
821 }
822 }
823
824
825 void GLAPIENTRY
826 _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
827 GLenum severity, GLint length,
828 const GLchar *buf)
829 {
830 const char *callerstr = "glDebugMessageInsert";
831
832 GET_CURRENT_CONTEXT(ctx);
833
834 if (!validate_params(ctx, INSERT, callerstr, source, type, severity))
835 return; /* GL_INVALID_ENUM */
836
837 message_insert(source, type, id, severity, length, buf, callerstr);
838 }
839
840
841 GLuint GLAPIENTRY
842 _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
843 GLenum *types, GLenum *ids, GLenum *severities,
844 GLsizei *lengths, GLchar *messageLog)
845 {
846 GET_CURRENT_CONTEXT(ctx);
847 GLuint ret;
848
849 if (!messageLog)
850 logSize = 0;
851
852 if (logSize < 0) {
853 _mesa_error(ctx, GL_INVALID_VALUE,
854 "glGetDebugMessageLog(logSize=%d : logSize must not be"
855 " negative)", logSize);
856 return 0;
857 }
858
859 for (ret = 0; ret < count; ret++) {
860 GLsizei written = get_msg(ctx, sources, types, ids, severities,
861 logSize, messageLog);
862 if (!written)
863 break;
864
865 if (messageLog) {
866 messageLog += written;
867 logSize -= written;
868 }
869 if (lengths) {
870 *lengths = written;
871 lengths++;
872 }
873
874 if (severities)
875 severities++;
876 if (sources)
877 sources++;
878 if (types)
879 types++;
880 if (ids)
881 ids++;
882 }
883
884 return ret;
885 }
886
887
888 void GLAPIENTRY
889 _mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
890 GLenum gl_severity, GLsizei count,
891 const GLuint *ids, GLboolean enabled)
892 {
893 const char *callerstr = "glDebugMessageControl";
894
895 GET_CURRENT_CONTEXT(ctx);
896
897 if (count < 0) {
898 _mesa_error(ctx, GL_INVALID_VALUE,
899 "%s(count=%d : count must not be negative)", callerstr,
900 count);
901 return;
902 }
903
904 if (!validate_params(ctx, CONTROL, callerstr, gl_source, gl_type,
905 gl_severity))
906 return; /* GL_INVALID_ENUM */
907
908 if (count && (gl_severity != GL_DONT_CARE || gl_type == GL_DONT_CARE
909 || gl_source == GL_DONT_CARE)) {
910 _mesa_error(ctx, GL_INVALID_OPERATION,
911 "%s(When passing an array of ids, severity must be"
912 " GL_DONT_CARE, and source and type must not be GL_DONT_CARE.",
913 callerstr);
914 return;
915 }
916
917 control_app_messages(ctx, gl_source, gl_type, gl_severity,
918 count, ids, enabled);
919 }
920
921
922 void GLAPIENTRY
923 _mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam)
924 {
925 GET_CURRENT_CONTEXT(ctx);
926 struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
927 if (debug) {
928 debug->Callback = callback;
929 debug->CallbackData = userParam;
930 }
931 }
932
933
934 void GLAPIENTRY
935 _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
936 const GLchar *message)
937 {
938 GET_CURRENT_CONTEXT(ctx);
939 struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
940 const char *callerstr = "glPushDebugGroup";
941 int s, t, sev;
942 GLint prevStackDepth;
943 GLint currStackDepth;
944 struct gl_debug_msg *emptySlot;
945
946 if (!debug)
947 return;
948
949 if (debug->GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
950 _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
951 return;
952 }
953
954 switch(source) {
955 case GL_DEBUG_SOURCE_APPLICATION:
956 case GL_DEBUG_SOURCE_THIRD_PARTY:
957 break;
958 default:
959 _mesa_error(ctx, GL_INVALID_ENUM, "bad value passed to %s"
960 "(source=0x%x)", callerstr, source);
961 return;
962 }
963
964 message_insert(source, GL_DEBUG_TYPE_PUSH_GROUP, id,
965 GL_DEBUG_SEVERITY_NOTIFICATION, length,
966 message, callerstr);
967
968 prevStackDepth = debug->GroupStackDepth;
969 debug->GroupStackDepth++;
970 currStackDepth = debug->GroupStackDepth;
971
972 /* pop reuses the message details from push so we store this */
973 if (length < 0)
974 length = strlen(message);
975 emptySlot = &debug->DebugGroupMsgs[debug->GroupStackDepth];
976 debug_message_store(emptySlot,
977 gl_enum_to_debug_source(source),
978 gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP),
979 id,
980 gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
981 length, message);
982
983 /* inherit the control volume of the debug group previously residing on
984 * the top of the debug group stack
985 */
986 for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
987 for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
988 /* copy id settings */
989 debug->Namespaces[currStackDepth][s][t].IDs =
990 _mesa_HashClone(debug->Namespaces[prevStackDepth][s][t].IDs);
991
992 for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
993 struct gl_debug_severity *entry, *prevEntry;
994 struct simple_node *node;
995
996 /* copy default settings for unknown ids */
997 debug->Defaults[currStackDepth][sev][s][t] =
998 debug->Defaults[prevStackDepth][sev][s][t];
999
1000 /* copy known id severity settings */
1001 make_empty_list(&debug->Namespaces[currStackDepth][s][t].Severity[sev]);
1002 foreach(node, &debug->Namespaces[prevStackDepth][s][t].Severity[sev]) {
1003 prevEntry = (struct gl_debug_severity *)node;
1004 entry = malloc(sizeof *entry);
1005 if (!entry)
1006 return;
1007
1008 entry->ID = prevEntry->ID;
1009 insert_at_tail(&debug->Namespaces[currStackDepth][s][t].Severity[sev], &entry->link);
1010 }
1011 }
1012 }
1013 }
1014 }
1015
1016
1017 void GLAPIENTRY
1018 _mesa_PopDebugGroup(void)
1019 {
1020 GET_CURRENT_CONTEXT(ctx);
1021 struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
1022 const char *callerstr = "glPopDebugGroup";
1023 struct gl_debug_msg *gdmessage;
1024 GLint prevStackDepth;
1025
1026 if (!debug)
1027 return;
1028
1029 if (debug->GroupStackDepth <= 0) {
1030 _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr);
1031 return;
1032 }
1033
1034 prevStackDepth = debug->GroupStackDepth;
1035 debug->GroupStackDepth--;
1036
1037 gdmessage = &debug->DebugGroupMsgs[prevStackDepth];
1038 /* using log_msg() directly here as verification of parameters
1039 * already done in push
1040 */
1041 log_msg(ctx, gdmessage->source,
1042 gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP),
1043 gdmessage->id,
1044 gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
1045 gdmessage->length, gdmessage->message);
1046
1047 if (gdmessage->message != (char*)out_of_memory)
1048 free(gdmessage->message);
1049 gdmessage->message = NULL;
1050 gdmessage->length = 0;
1051
1052 /* free popped debug group data */
1053 free_errors_data(ctx, prevStackDepth);
1054 }
1055
1056
1057 void
1058 _mesa_init_errors(struct gl_context *ctx)
1059 {
1060 /* no-op */
1061 }
1062
1063
1064 /**
1065 * Loop through debug group stack tearing down states for
1066 * filtering debug messages. Then free debug output state.
1067 */
1068 void
1069 _mesa_free_errors_data(struct gl_context *ctx)
1070 {
1071 if (ctx->Debug) {
1072 GLint i;
1073
1074 for (i = 0; i <= ctx->Debug->GroupStackDepth; i++) {
1075 free_errors_data(ctx, i);
1076 }
1077 free(ctx->Debug);
1078 /* set to NULL just in case it is used before context is completely gone. */
1079 ctx->Debug = NULL;
1080 }
1081 }
1082
1083
1084 /**********************************************************************/
1085 /** \name Diagnostics */
1086 /*@{*/
1087
1088 static void
1089 output_if_debug(const char *prefixString, const char *outputString,
1090 GLboolean newline)
1091 {
1092 static int debug = -1;
1093 static FILE *fout = NULL;
1094
1095 /* Init the local 'debug' var once.
1096 * Note: the _mesa_init_debug() function should have been called
1097 * by now so MESA_DEBUG_FLAGS will be initialized.
1098 */
1099 if (debug == -1) {
1100 /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
1101 * etc to the named file. Otherwise, output to stderr.
1102 */
1103 const char *logFile = _mesa_getenv("MESA_LOG_FILE");
1104 if (logFile)
1105 fout = fopen(logFile, "w");
1106 if (!fout)
1107 fout = stderr;
1108 #ifdef DEBUG
1109 /* in debug builds, print messages unless MESA_DEBUG="silent" */
1110 if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
1111 debug = 0;
1112 else
1113 debug = 1;
1114 #else
1115 /* in release builds, be silent unless MESA_DEBUG is set */
1116 debug = _mesa_getenv("MESA_DEBUG") != NULL;
1117 #endif
1118 }
1119
1120 /* Now only print the string if we're required to do so. */
1121 if (debug) {
1122 fprintf(fout, "%s: %s", prefixString, outputString);
1123 if (newline)
1124 fprintf(fout, "\n");
1125 fflush(fout);
1126
1127 #if defined(_WIN32) && !defined(_WIN32_WCE)
1128 /* stderr from windows applications without console is not usually
1129 * visible, so communicate with the debugger instead */
1130 {
1131 char buf[4096];
1132 _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
1133 OutputDebugStringA(buf);
1134 }
1135 #endif
1136 }
1137 }
1138
1139
1140 /**
1141 * When a new type of error is recorded, print a message describing
1142 * previous errors which were accumulated.
1143 */
1144 static void
1145 flush_delayed_errors( struct gl_context *ctx )
1146 {
1147 char s[MAX_DEBUG_MESSAGE_LENGTH];
1148
1149 if (ctx->ErrorDebugCount) {
1150 _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors",
1151 ctx->ErrorDebugCount,
1152 _mesa_lookup_enum_by_nr(ctx->ErrorValue));
1153
1154 output_if_debug("Mesa", s, GL_TRUE);
1155
1156 ctx->ErrorDebugCount = 0;
1157 }
1158 }
1159
1160
1161 /**
1162 * Report a warning (a recoverable error condition) to stderr if
1163 * either DEBUG is defined or the MESA_DEBUG env var is set.
1164 *
1165 * \param ctx GL context.
1166 * \param fmtString printf()-like format string.
1167 */
1168 void
1169 _mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
1170 {
1171 char str[MAX_DEBUG_MESSAGE_LENGTH];
1172 va_list args;
1173 va_start( args, fmtString );
1174 (void) _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
1175 va_end( args );
1176
1177 if (ctx)
1178 flush_delayed_errors( ctx );
1179
1180 output_if_debug("Mesa warning", str, GL_TRUE);
1181 }
1182
1183
1184 /**
1185 * Report an internal implementation problem.
1186 * Prints the message to stderr via fprintf().
1187 *
1188 * \param ctx GL context.
1189 * \param fmtString problem description string.
1190 */
1191 void
1192 _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
1193 {
1194 va_list args;
1195 char str[MAX_DEBUG_MESSAGE_LENGTH];
1196 static int numCalls = 0;
1197
1198 (void) ctx;
1199
1200 if (numCalls < 50) {
1201 numCalls++;
1202
1203 va_start( args, fmtString );
1204 _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
1205 va_end( args );
1206 fprintf(stderr, "Mesa %s implementation error: %s\n",
1207 PACKAGE_VERSION, str);
1208 fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n");
1209 }
1210 }
1211
1212
1213 static GLboolean
1214 should_output(struct gl_context *ctx, GLenum error, const char *fmtString)
1215 {
1216 static GLint debug = -1;
1217
1218 /* Check debug environment variable only once:
1219 */
1220 if (debug == -1) {
1221 const char *debugEnv = _mesa_getenv("MESA_DEBUG");
1222
1223 #ifdef DEBUG
1224 if (debugEnv && strstr(debugEnv, "silent"))
1225 debug = GL_FALSE;
1226 else
1227 debug = GL_TRUE;
1228 #else
1229 if (debugEnv)
1230 debug = GL_TRUE;
1231 else
1232 debug = GL_FALSE;
1233 #endif
1234 }
1235
1236 if (debug) {
1237 if (ctx->ErrorValue != error ||
1238 ctx->ErrorDebugFmtString != fmtString) {
1239 flush_delayed_errors( ctx );
1240 ctx->ErrorDebugFmtString = fmtString;
1241 ctx->ErrorDebugCount = 0;
1242 return GL_TRUE;
1243 }
1244 ctx->ErrorDebugCount++;
1245 }
1246 return GL_FALSE;
1247 }
1248
1249
1250 void
1251 _mesa_gl_debug(struct gl_context *ctx,
1252 GLuint *id,
1253 enum mesa_debug_type type,
1254 enum mesa_debug_severity severity,
1255 const char *fmtString, ...)
1256 {
1257 char s[MAX_DEBUG_MESSAGE_LENGTH];
1258 int len;
1259 va_list args;
1260
1261 debug_get_id(id);
1262
1263 va_start(args, fmtString);
1264 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1265 va_end(args);
1266
1267 log_msg(ctx, MESA_DEBUG_SOURCE_API, type, *id, severity, len, s);
1268 }
1269
1270
1271 /**
1272 * Record an OpenGL state error. These usually occur when the user
1273 * passes invalid parameters to a GL function.
1274 *
1275 * If debugging is enabled (either at compile-time via the DEBUG macro, or
1276 * run-time via the MESA_DEBUG environment variable), report the error with
1277 * _mesa_debug().
1278 *
1279 * \param ctx the GL context.
1280 * \param error the error value.
1281 * \param fmtString printf() style format string, followed by optional args
1282 */
1283 void
1284 _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
1285 {
1286 GLboolean do_output, do_log;
1287 /* Ideally this would be set up by the caller, so that we had proper IDs
1288 * per different message.
1289 */
1290 static GLuint error_msg_id = 0;
1291
1292 debug_get_id(&error_msg_id);
1293
1294 do_output = should_output(ctx, error, fmtString);
1295 do_log = should_log(ctx,
1296 MESA_DEBUG_SOURCE_API,
1297 MESA_DEBUG_TYPE_ERROR,
1298 error_msg_id,
1299 MESA_DEBUG_SEVERITY_HIGH);
1300
1301 if (do_output || do_log) {
1302 char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
1303 int len;
1304 va_list args;
1305
1306 va_start(args, fmtString);
1307 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1308 va_end(args);
1309
1310 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
1311 /* Too long error message. Whoever calls _mesa_error should use
1312 * shorter strings.
1313 */
1314 ASSERT(0);
1315 return;
1316 }
1317
1318 len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
1319 _mesa_lookup_enum_by_nr(error), s);
1320 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
1321 /* Same as above. */
1322 ASSERT(0);
1323 return;
1324 }
1325
1326 /* Print the error to stderr if needed. */
1327 if (do_output) {
1328 output_if_debug("Mesa: User error", s2, GL_TRUE);
1329 }
1330
1331 /* Log the error via ARB_debug_output if needed.*/
1332 if (do_log) {
1333 log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR,
1334 error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2);
1335 }
1336 }
1337
1338 /* Set the GL context error state for glGetError. */
1339 _mesa_record_error(ctx, error);
1340 }
1341
1342
1343 /**
1344 * Report debug information. Print error message to stderr via fprintf().
1345 * No-op if DEBUG mode not enabled.
1346 *
1347 * \param ctx GL context.
1348 * \param fmtString printf()-style format string, followed by optional args.
1349 */
1350 void
1351 _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
1352 {
1353 #ifdef DEBUG
1354 char s[MAX_DEBUG_MESSAGE_LENGTH];
1355 va_list args;
1356 va_start(args, fmtString);
1357 _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1358 va_end(args);
1359 output_if_debug("Mesa", s, GL_FALSE);
1360 #endif /* DEBUG */
1361 (void) ctx;
1362 (void) fmtString;
1363 }
1364
1365
1366 /**
1367 * Report debug information from the shader compiler via GL_ARB_debug_output.
1368 *
1369 * \param ctx GL context.
1370 * \param type The namespace to which this message belongs.
1371 * \param id The message ID within the given namespace.
1372 * \param msg The message to output. Need not be null-terminated.
1373 * \param len The length of 'msg'. If negative, 'msg' must be null-terminated.
1374 */
1375 void
1376 _mesa_shader_debug( struct gl_context *ctx, GLenum type, GLuint *id,
1377 const char *msg, int len )
1378 {
1379 enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
1380 enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH;
1381
1382 debug_get_id(id);
1383
1384 if (len < 0)
1385 len = strlen(msg);
1386
1387 /* Truncate the message if necessary. */
1388 if (len >= MAX_DEBUG_MESSAGE_LENGTH)
1389 len = MAX_DEBUG_MESSAGE_LENGTH - 1;
1390
1391 log_msg(ctx, source, type, *id, severity, len, msg);
1392 }
1393
1394 /*@}*/