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