mesa: Restore 78-column wrapping of license text in C-style comments.
[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 * Version: 7.1
9 *
10 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32 #include "errors.h"
33 #include "enums.h"
34 #include "imports.h"
35 #include "context.h"
36 #include "dispatch.h"
37 #include "hash.h"
38 #include "mtypes.h"
39 #include "version.h"
40 #include "hash_table.h"
41 #include "glapi/glthread.h"
42
43 _glthread_DECLARE_STATIC_MUTEX(DynamicIDMutex);
44 static GLuint NextDynamicID = 1;
45
46 struct gl_debug_severity
47 {
48 struct simple_node link;
49 GLuint ID;
50 };
51
52 static char out_of_memory[] = "Debugging error: out of memory";
53
54 static const GLenum debug_source_enums[] = {
55 GL_DEBUG_SOURCE_API,
56 GL_DEBUG_SOURCE_WINDOW_SYSTEM,
57 GL_DEBUG_SOURCE_SHADER_COMPILER,
58 GL_DEBUG_SOURCE_THIRD_PARTY,
59 GL_DEBUG_SOURCE_APPLICATION,
60 GL_DEBUG_SOURCE_OTHER,
61 };
62
63 static const GLenum debug_type_enums[] = {
64 GL_DEBUG_TYPE_ERROR,
65 GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR,
66 GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR,
67 GL_DEBUG_TYPE_PORTABILITY,
68 GL_DEBUG_TYPE_PERFORMANCE,
69 GL_DEBUG_TYPE_OTHER,
70 };
71
72 static const GLenum debug_severity_enums[] = {
73 GL_DEBUG_SEVERITY_LOW,
74 GL_DEBUG_SEVERITY_MEDIUM,
75 GL_DEBUG_SEVERITY_HIGH,
76 };
77
78 static enum mesa_debug_source
79 gl_enum_to_debug_source(GLenum e)
80 {
81 int i;
82
83 for (i = 0; i < Elements(debug_source_enums); i++) {
84 if (debug_source_enums[i] == e)
85 break;
86 }
87 return i;
88 }
89
90 static enum mesa_debug_type
91 gl_enum_to_debug_type(GLenum e)
92 {
93 int i;
94
95 for (i = 0; i < Elements(debug_type_enums); i++) {
96 if (debug_type_enums[i] == e)
97 break;
98 }
99 return i;
100 }
101
102 static enum mesa_debug_severity
103 gl_enum_to_debug_severity(GLenum e)
104 {
105 int i;
106
107 for (i = 0; i < Elements(debug_severity_enums); i++) {
108 if (debug_severity_enums[i] == e)
109 break;
110 }
111 return i;
112 }
113
114 /**
115 * Handles generating a GL_ARB_debug_output message ID generated by the GL or
116 * GLSL compiler.
117 *
118 * The GL API has this "ID" mechanism, where the intention is to allow a
119 * client to filter in/out messages based on source, type, and ID. Of course,
120 * building a giant enum list of all debug output messages that Mesa might
121 * generate is ridiculous, so instead we have our caller pass us a pointer to
122 * static storage where the ID should get stored. This ID will be shared
123 * across all contexts for that message (which seems like a desirable
124 * property, even if it's not expected by the spec), but note that it won't be
125 * the same between executions if messages aren't generated in the same order.
126 */
127 static void
128 debug_get_id(GLuint *id)
129 {
130 if (!(*id)) {
131 _glthread_LOCK_MUTEX(DynamicIDMutex);
132 if (!(*id))
133 *id = NextDynamicID++;
134 _glthread_UNLOCK_MUTEX(DynamicIDMutex);
135 }
136 }
137
138 /*
139 * We store a bitfield in the hash table, with five possible values total.
140 *
141 * The ENABLED_BIT's purpose is self-explanatory.
142 *
143 * The FOUND_BIT is needed to differentiate the value of DISABLED from
144 * the value returned by HashTableLookup() when it can't find the given key.
145 *
146 * The KNOWN_SEVERITY bit is a bit complicated:
147 *
148 * A client may call Control() with an array of IDs, then call Control()
149 * on all message IDs of a certain severity, then Insert() one of the
150 * previously specified IDs, giving us a known severity level, then call
151 * Control() on all message IDs of a certain severity level again.
152 *
153 * After the first call, those IDs will have a FOUND_BIT, but will not
154 * exist in any severity-specific list, so the second call will not
155 * impact them. This is undesirable but unavoidable given the API:
156 * The only entrypoint that gives a severity for a client-defined ID
157 * is the Insert() call.
158 *
159 * For the sake of Control(), we want to maintain the invariant
160 * that an ID will either appear in none of the three severity lists,
161 * or appear once, to minimize pointless duplication and potential surprises.
162 *
163 * Because Insert() is the only place that will learn an ID's severity,
164 * it should insert an ID into the appropriate list, but only if the ID
165 * doesn't exist in it or any other list yet. Because searching all three
166 * lists at O(n) is needlessly expensive, we store KNOWN_SEVERITY.
167 */
168 enum {
169 FOUND_BIT = 1 << 0,
170 ENABLED_BIT = 1 << 1,
171 KNOWN_SEVERITY = 1 << 2,
172
173 /* HashTable reserves zero as a return value meaning 'not found' */
174 NOT_FOUND = 0,
175 DISABLED = FOUND_BIT,
176 ENABLED = ENABLED_BIT | FOUND_BIT
177 };
178
179 /**
180 * Returns the state of the given message source/type/ID tuple.
181 */
182 static GLboolean
183 should_log(struct gl_context *ctx,
184 enum mesa_debug_source source,
185 enum mesa_debug_type type,
186 GLuint id,
187 enum mesa_debug_severity severity)
188 {
189 struct gl_debug_namespace *nspace =
190 &ctx->Debug.Namespaces[source][type];
191 uintptr_t state;
192
193 /* In addition to not being able to store zero as a value, HashTable also
194 can't use zero as a key. */
195 if (id)
196 state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
197 else
198 state = nspace->ZeroID;
199
200 /* Only do this once for each ID. This makes sure the ID exists in,
201 at most, one list, and does not pointlessly appear multiple times. */
202 if (!(state & KNOWN_SEVERITY)) {
203 struct gl_debug_severity *entry;
204
205 if (state == NOT_FOUND) {
206 if (ctx->Debug.Defaults[severity][source][type])
207 state = ENABLED;
208 else
209 state = DISABLED;
210 }
211
212 entry = malloc(sizeof *entry);
213 if (!entry)
214 goto out;
215
216 state |= KNOWN_SEVERITY;
217
218 if (id)
219 _mesa_HashInsert(nspace->IDs, id, (void*)state);
220 else
221 nspace->ZeroID = state;
222
223 entry->ID = id;
224 insert_at_tail(&nspace->Severity[severity], &entry->link);
225 }
226
227 out:
228 return !!(state & ENABLED_BIT);
229 }
230
231 /**
232 * Sets the state of the given message source/type/ID tuple.
233 */
234 static void
235 set_message_state(struct gl_context *ctx,
236 enum mesa_debug_source source,
237 enum mesa_debug_type type,
238 GLuint id, GLboolean enabled)
239 {
240 struct gl_debug_namespace *nspace =
241 &ctx->Debug.Namespaces[source][type];
242 uintptr_t state;
243
244 /* In addition to not being able to store zero as a value, HashTable also
245 can't use zero as a key. */
246 if (id)
247 state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
248 else
249 state = nspace->ZeroID;
250
251 if (state == NOT_FOUND)
252 state = enabled ? ENABLED : DISABLED;
253 else {
254 if (enabled)
255 state |= ENABLED_BIT;
256 else
257 state &= ~ENABLED_BIT;
258 }
259
260 if (id)
261 _mesa_HashInsert(nspace->IDs, id, (void*)state);
262 else
263 nspace->ZeroID = state;
264 }
265
266 /**
267 * 'buf' is not necessarily a null-terminated string. When logging, copy
268 * 'len' characters from it, store them in a new, null-terminated string,
269 * and remember the number of bytes used by that string, *including*
270 * the null terminator this time.
271 */
272 static void
273 _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source,
274 enum mesa_debug_type type, GLuint id,
275 enum mesa_debug_severity severity, GLint len, const char *buf)
276 {
277 GLint nextEmpty;
278 struct gl_debug_msg *emptySlot;
279
280 assert(len >= 0 && len < MAX_DEBUG_MESSAGE_LENGTH);
281
282 if (!should_log(ctx, source, type, id, severity))
283 return;
284
285 if (ctx->Debug.Callback) {
286 ctx->Debug.Callback(debug_source_enums[source],
287 debug_type_enums[type],
288 id,
289 debug_severity_enums[severity],
290 len, buf, ctx->Debug.CallbackData);
291 return;
292 }
293
294 if (ctx->Debug.NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
295 return;
296
297 nextEmpty = (ctx->Debug.NextMsg + ctx->Debug.NumMessages)
298 % MAX_DEBUG_LOGGED_MESSAGES;
299 emptySlot = &ctx->Debug.Log[nextEmpty];
300
301 assert(!emptySlot->message && !emptySlot->length);
302
303 emptySlot->message = malloc(len+1);
304 if (emptySlot->message) {
305 (void) strncpy(emptySlot->message, buf, (size_t)len);
306 emptySlot->message[len] = '\0';
307
308 emptySlot->length = len+1;
309 emptySlot->source = source;
310 emptySlot->type = type;
311 emptySlot->id = id;
312 emptySlot->severity = severity;
313 } else {
314 static GLuint oom_msg_id = 0;
315 debug_get_id(&oom_msg_id);
316
317 /* malloc failed! */
318 emptySlot->message = out_of_memory;
319 emptySlot->length = strlen(out_of_memory)+1;
320 emptySlot->source = MESA_DEBUG_SOURCE_OTHER;
321 emptySlot->type = MESA_DEBUG_TYPE_ERROR;
322 emptySlot->id = oom_msg_id;
323 emptySlot->severity = MESA_DEBUG_SEVERITY_HIGH;
324 }
325
326 if (ctx->Debug.NumMessages == 0)
327 ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length;
328
329 ctx->Debug.NumMessages++;
330 }
331
332 /**
333 * Pop the oldest debug message out of the log.
334 * Writes the message string, including the null terminator, into 'buf',
335 * using up to 'bufSize' bytes. If 'bufSize' is too small, or
336 * if 'buf' is NULL, nothing is written.
337 *
338 * Returns the number of bytes written on success, or when 'buf' is NULL,
339 * the number that would have been written. A return value of 0
340 * indicates failure.
341 */
342 static GLsizei
343 _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type,
344 GLuint *id, GLenum *severity, GLsizei bufSize, char *buf)
345 {
346 struct gl_debug_msg *msg;
347 GLsizei length;
348
349 if (ctx->Debug.NumMessages == 0)
350 return 0;
351
352 msg = &ctx->Debug.Log[ctx->Debug.NextMsg];
353 length = msg->length;
354
355 assert(length > 0 && length == ctx->Debug.NextMsgLength);
356
357 if (bufSize < length && buf != NULL)
358 return 0;
359
360 if (severity)
361 *severity = debug_severity_enums[msg->severity];
362 if (source)
363 *source = debug_source_enums[msg->source];
364 if (type)
365 *type = debug_type_enums[msg->type];
366 if (id)
367 *id = msg->id;
368
369 if (buf) {
370 assert(msg->message[length-1] == '\0');
371 (void) strncpy(buf, msg->message, (size_t)length);
372 }
373
374 if (msg->message != (char*)out_of_memory)
375 free(msg->message);
376 msg->message = NULL;
377 msg->length = 0;
378
379 ctx->Debug.NumMessages--;
380 ctx->Debug.NextMsg++;
381 ctx->Debug.NextMsg %= MAX_DEBUG_LOGGED_MESSAGES;
382 ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length;
383
384 return length;
385 }
386
387 /**
388 * Verify that source, type, and severity are valid enums.
389 * glDebugMessageInsertARB only accepts two values for 'source',
390 * and glDebugMessageControlARB will additionally accept GL_DONT_CARE
391 * in any parameter, so handle those cases specially.
392 */
393 static GLboolean
394 validate_params(struct gl_context *ctx, unsigned caller,
395 GLenum source, GLenum type, GLenum severity)
396 {
397 #define INSERT 1
398 #define CONTROL 2
399 switch(source) {
400 case GL_DEBUG_SOURCE_APPLICATION_ARB:
401 case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
402 break;
403 case GL_DEBUG_SOURCE_API_ARB:
404 case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
405 case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
406 case GL_DEBUG_SOURCE_OTHER_ARB:
407 if (caller != INSERT)
408 break;
409 case GL_DONT_CARE:
410 if (caller == CONTROL)
411 break;
412 default:
413 goto error;
414 }
415
416 switch(type) {
417 case GL_DEBUG_TYPE_ERROR_ARB:
418 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
419 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
420 case GL_DEBUG_TYPE_PERFORMANCE_ARB:
421 case GL_DEBUG_TYPE_PORTABILITY_ARB:
422 case GL_DEBUG_TYPE_OTHER_ARB:
423 break;
424 case GL_DONT_CARE:
425 if (caller == CONTROL)
426 break;
427 default:
428 goto error;
429 }
430
431 switch(severity) {
432 case GL_DEBUG_SEVERITY_HIGH_ARB:
433 case GL_DEBUG_SEVERITY_MEDIUM_ARB:
434 case GL_DEBUG_SEVERITY_LOW_ARB:
435 break;
436 case GL_DONT_CARE:
437 if (caller == CONTROL)
438 break;
439 default:
440 goto error;
441 }
442 return GL_TRUE;
443
444 error:
445 {
446 const char *callerstr;
447 if (caller == INSERT)
448 callerstr = "glDebugMessageInsertARB";
449 else if (caller == CONTROL)
450 callerstr = "glDebugMessageControlARB";
451 else
452 return GL_FALSE;
453
454 _mesa_error( ctx, GL_INVALID_ENUM, "bad values passed to %s"
455 "(source=0x%x, type=0x%x, severity=0x%x)", callerstr,
456 source, type, severity);
457 }
458 return GL_FALSE;
459 }
460
461 void GLAPIENTRY
462 _mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id,
463 GLenum severity, GLint length,
464 const GLcharARB* buf)
465 {
466 GET_CURRENT_CONTEXT(ctx);
467
468 if (!validate_params(ctx, INSERT, source, type, severity))
469 return; /* GL_INVALID_ENUM */
470
471 if (length < 0)
472 length = strlen(buf);
473
474 if (length >= MAX_DEBUG_MESSAGE_LENGTH) {
475 _mesa_error(ctx, GL_INVALID_VALUE, "glDebugMessageInsertARB"
476 "(length=%d, which is not less than "
477 "GL_MAX_DEBUG_MESSAGE_LENGTH_ARB=%d)", length,
478 MAX_DEBUG_MESSAGE_LENGTH);
479 return;
480 }
481
482 _mesa_log_msg(ctx,
483 gl_enum_to_debug_source(source),
484 gl_enum_to_debug_type(type), id,
485 gl_enum_to_debug_severity(severity), length, buf);
486 }
487
488 GLuint GLAPIENTRY
489 _mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources,
490 GLenum* types, GLenum* ids, GLenum* severities,
491 GLsizei* lengths, GLcharARB* messageLog)
492 {
493 GET_CURRENT_CONTEXT(ctx);
494 GLuint ret;
495
496 if (!messageLog)
497 logSize = 0;
498
499 if (logSize < 0) {
500 _mesa_error(ctx, GL_INVALID_VALUE, "glGetDebugMessageLogARB"
501 "(logSize=%d : logSize must not be negative)", logSize);
502 return 0;
503 }
504
505 for (ret = 0; ret < count; ret++) {
506 GLsizei written = _mesa_get_msg(ctx, sources, types, ids, severities,
507 logSize, messageLog);
508 if (!written)
509 break;
510
511 if (messageLog) {
512 messageLog += written;
513 logSize -= written;
514 }
515 if (lengths) {
516 *lengths = written;
517 lengths++;
518 }
519
520 if (severities)
521 severities++;
522 if (sources)
523 sources++;
524 if (types)
525 types++;
526 if (ids)
527 ids++;
528 }
529
530 return ret;
531 }
532
533 /**
534 * Set the state of all message IDs found in the given intersection of
535 * 'source', 'type', and 'severity'. The _COUNT enum can be used for
536 * GL_DONT_CARE (include all messages in the class).
537 *
538 * This requires both setting the state of all previously seen message
539 * IDs in the hash table, and setting the default state for all
540 * applicable combinations of source/type/severity, so that all the
541 * yet-unknown message IDs that may be used in the future will be
542 * impacted as if they were already known.
543 */
544 static void
545 control_messages(struct gl_context *ctx,
546 enum mesa_debug_source source,
547 enum mesa_debug_type type,
548 enum mesa_debug_severity severity,
549 GLboolean enabled)
550 {
551 int s, t, sev, smax, tmax, sevmax;
552
553 if (source == MESA_DEBUG_SOURCE_COUNT) {
554 source = 0;
555 smax = MESA_DEBUG_SOURCE_COUNT;
556 } else {
557 smax = source+1;
558 }
559
560 if (type == MESA_DEBUG_TYPE_COUNT) {
561 type = 0;
562 tmax = MESA_DEBUG_TYPE_COUNT;
563 } else {
564 tmax = type+1;
565 }
566
567 if (severity == MESA_DEBUG_SEVERITY_COUNT) {
568 severity = 0;
569 sevmax = MESA_DEBUG_SEVERITY_COUNT;
570 } else {
571 sevmax = severity+1;
572 }
573
574 for (sev = severity; sev < sevmax; sev++)
575 for (s = source; s < smax; s++)
576 for (t = type; t < tmax; t++) {
577 struct simple_node *node;
578 struct gl_debug_severity *entry;
579
580 /* change the default for IDs we've never seen before. */
581 ctx->Debug.Defaults[sev][s][t] = enabled;
582
583 /* Now change the state of IDs we *have* seen... */
584 foreach(node, &ctx->Debug.Namespaces[s][t].Severity[sev]) {
585 entry = (struct gl_debug_severity *)node;
586 set_message_state(ctx, s, t, entry->ID, enabled);
587 }
588 }
589 }
590
591 /**
592 * Debugging-message namespaces with the source APPLICATION or THIRD_PARTY
593 * require special handling, since the IDs in them are controlled by clients,
594 * not the OpenGL implementation.
595 *
596 * 'count' is the length of the array 'ids'. If 'count' is nonzero, all
597 * the given IDs in the namespace defined by 'esource' and 'etype'
598 * will be affected.
599 *
600 * If 'count' is zero, this sets the state of all IDs that match
601 * the combination of 'esource', 'etype', and 'eseverity'.
602 */
603 static void
604 control_app_messages(struct gl_context *ctx, GLenum esource, GLenum etype,
605 GLenum eseverity, GLsizei count, const GLuint *ids,
606 GLboolean enabled)
607 {
608 GLsizei i;
609 enum mesa_debug_source source = gl_enum_to_debug_source(esource);
610 enum mesa_debug_type type = gl_enum_to_debug_type(etype);
611 enum mesa_debug_severity severity = gl_enum_to_debug_severity(eseverity);
612
613 if (count)
614 assert(severity == MESA_DEBUG_SEVERITY_COUNT
615 && type != MESA_DEBUG_TYPE_COUNT
616 && source != MESA_DEBUG_SOURCE_COUNT);
617
618 for (i = 0; i < count; i++)
619 set_message_state(ctx, source, type, ids[i], enabled);
620
621 if (count)
622 return;
623
624 control_messages(ctx, source, type, severity, enabled);
625 }
626
627 void GLAPIENTRY
628 _mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type,
629 GLenum gl_severity,
630 GLsizei count, const GLuint *ids,
631 GLboolean enabled)
632 {
633 enum mesa_debug_source source;
634 enum mesa_debug_type type;
635 enum mesa_debug_severity severity;
636 GET_CURRENT_CONTEXT(ctx);
637
638 if (count < 0) {
639 _mesa_error(ctx, GL_INVALID_VALUE, "glDebugMessageControlARB"
640 "(count=%d : count must not be negative)", count);
641 return;
642 }
643
644 if (!validate_params(ctx, CONTROL, gl_source, gl_type, gl_severity))
645 return; /* GL_INVALID_ENUM */
646
647 if (count && (gl_severity != GL_DONT_CARE || gl_type == GL_DONT_CARE
648 || gl_source == GL_DONT_CARE)) {
649 _mesa_error(ctx, GL_INVALID_OPERATION, "glDebugMessageControlARB"
650 "(When passing an array of ids, severity must be"
651 " GL_DONT_CARE, and source and type must not be GL_DONT_CARE.");
652 return;
653 }
654
655 source = gl_enum_to_debug_source(gl_source);
656 type = gl_enum_to_debug_type(gl_type);
657 severity = gl_enum_to_debug_severity(gl_severity);
658
659 control_app_messages(ctx, source, type, severity, count, ids, enabled);
660 }
661
662 void GLAPIENTRY
663 _mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, const GLvoid *userParam)
664 {
665 GET_CURRENT_CONTEXT(ctx);
666 ctx->Debug.Callback = callback;
667 ctx->Debug.CallbackData = (void *) userParam;
668 }
669
670 void
671 _mesa_init_errors(struct gl_context *ctx)
672 {
673 int s, t, sev;
674
675 ctx->Debug.Callback = NULL;
676 ctx->Debug.SyncOutput = GL_FALSE;
677 ctx->Debug.Log[0].length = 0;
678 ctx->Debug.NumMessages = 0;
679 ctx->Debug.NextMsg = 0;
680 ctx->Debug.NextMsgLength = 0;
681
682 /* Enable all the messages with severity HIGH or MEDIUM by default. */
683 memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH], GL_TRUE,
684 sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH]);
685 memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE,
686 sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM]);
687 memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW], GL_FALSE,
688 sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW]);
689
690 /* Initialize state for filtering known debug messages. */
691 for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
692 for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
693 ctx->Debug.Namespaces[s][t].IDs = _mesa_NewHashTable();
694 assert(ctx->Debug.Namespaces[s][t].IDs);
695
696 for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++)
697 make_empty_list(&ctx->Debug.Namespaces[s][t].Severity[sev]);
698 }
699 }
700
701 static void
702 do_nothing(GLuint key, void *data, void *userData)
703 {
704 }
705
706 void
707 _mesa_free_errors_data(struct gl_context *ctx)
708 {
709 enum mesa_debug_type t;
710 enum mesa_debug_source s;
711 enum mesa_debug_severity sev;
712
713 /* Tear down state for filtering debug messages. */
714 for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
715 for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
716 _mesa_HashDeleteAll(ctx->Debug.Namespaces[s][t].IDs, do_nothing, NULL);
717 _mesa_DeleteHashTable(ctx->Debug.Namespaces[s][t].IDs);
718 for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
719 struct simple_node *node, *tmp;
720 struct gl_debug_severity *entry;
721
722 foreach_s(node, tmp, &ctx->Debug.Namespaces[s][t].Severity[sev]) {
723 entry = (struct gl_debug_severity *)node;
724 free(entry);
725 }
726 }
727 }
728 }
729
730 /**********************************************************************/
731 /** \name Diagnostics */
732 /*@{*/
733
734 static void
735 output_if_debug(const char *prefixString, const char *outputString,
736 GLboolean newline)
737 {
738 static int debug = -1;
739 static FILE *fout = NULL;
740
741 /* Init the local 'debug' var once.
742 * Note: the _mesa_init_debug() function should have been called
743 * by now so MESA_DEBUG_FLAGS will be initialized.
744 */
745 if (debug == -1) {
746 /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
747 * etc to the named file. Otherwise, output to stderr.
748 */
749 const char *logFile = _mesa_getenv("MESA_LOG_FILE");
750 if (logFile)
751 fout = fopen(logFile, "w");
752 if (!fout)
753 fout = stderr;
754 #ifdef DEBUG
755 /* in debug builds, print messages unless MESA_DEBUG="silent" */
756 if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
757 debug = 0;
758 else
759 debug = 1;
760 #else
761 /* in release builds, be silent unless MESA_DEBUG is set */
762 debug = _mesa_getenv("MESA_DEBUG") != NULL;
763 #endif
764 }
765
766 /* Now only print the string if we're required to do so. */
767 if (debug) {
768 fprintf(fout, "%s: %s", prefixString, outputString);
769 if (newline)
770 fprintf(fout, "\n");
771 fflush(fout);
772
773 #if defined(_WIN32) && !defined(_WIN32_WCE)
774 /* stderr from windows applications without console is not usually
775 * visible, so communicate with the debugger instead */
776 {
777 char buf[4096];
778 _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
779 OutputDebugStringA(buf);
780 }
781 #endif
782 }
783 }
784
785 /**
786 * When a new type of error is recorded, print a message describing
787 * previous errors which were accumulated.
788 */
789 static void
790 flush_delayed_errors( struct gl_context *ctx )
791 {
792 char s[MAX_DEBUG_MESSAGE_LENGTH];
793
794 if (ctx->ErrorDebugCount) {
795 _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors",
796 ctx->ErrorDebugCount,
797 _mesa_lookup_enum_by_nr(ctx->ErrorValue));
798
799 output_if_debug("Mesa", s, GL_TRUE);
800
801 ctx->ErrorDebugCount = 0;
802 }
803 }
804
805
806 /**
807 * Report a warning (a recoverable error condition) to stderr if
808 * either DEBUG is defined or the MESA_DEBUG env var is set.
809 *
810 * \param ctx GL context.
811 * \param fmtString printf()-like format string.
812 */
813 void
814 _mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
815 {
816 char str[MAX_DEBUG_MESSAGE_LENGTH];
817 va_list args;
818 va_start( args, fmtString );
819 (void) _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
820 va_end( args );
821
822 if (ctx)
823 flush_delayed_errors( ctx );
824
825 output_if_debug("Mesa warning", str, GL_TRUE);
826 }
827
828
829 /**
830 * Report an internal implementation problem.
831 * Prints the message to stderr via fprintf().
832 *
833 * \param ctx GL context.
834 * \param fmtString problem description string.
835 */
836 void
837 _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
838 {
839 va_list args;
840 char str[MAX_DEBUG_MESSAGE_LENGTH];
841 static int numCalls = 0;
842
843 (void) ctx;
844
845 if (numCalls < 50) {
846 numCalls++;
847
848 va_start( args, fmtString );
849 _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
850 va_end( args );
851 fprintf(stderr, "Mesa %s implementation error: %s\n",
852 PACKAGE_VERSION, str);
853 fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n");
854 }
855 }
856
857 static GLboolean
858 should_output(struct gl_context *ctx, GLenum error, const char *fmtString)
859 {
860 static GLint debug = -1;
861
862 /* Check debug environment variable only once:
863 */
864 if (debug == -1) {
865 const char *debugEnv = _mesa_getenv("MESA_DEBUG");
866
867 #ifdef DEBUG
868 if (debugEnv && strstr(debugEnv, "silent"))
869 debug = GL_FALSE;
870 else
871 debug = GL_TRUE;
872 #else
873 if (debugEnv)
874 debug = GL_TRUE;
875 else
876 debug = GL_FALSE;
877 #endif
878 }
879
880 if (debug) {
881 if (ctx->ErrorValue != error ||
882 ctx->ErrorDebugFmtString != fmtString) {
883 flush_delayed_errors( ctx );
884 ctx->ErrorDebugFmtString = fmtString;
885 ctx->ErrorDebugCount = 0;
886 return GL_TRUE;
887 }
888 ctx->ErrorDebugCount++;
889 }
890 return GL_FALSE;
891 }
892
893 void
894 _mesa_gl_debug(struct gl_context *ctx,
895 GLuint *id,
896 enum mesa_debug_type type,
897 enum mesa_debug_severity severity,
898 const char *fmtString, ...)
899 {
900 char s[MAX_DEBUG_MESSAGE_LENGTH];
901 int len;
902 va_list args;
903
904 debug_get_id(id);
905
906 va_start(args, fmtString);
907 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
908 va_end(args);
909
910 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, type,
911 *id, severity, len, s);
912 }
913
914
915 /**
916 * Record an OpenGL state error. These usually occur when the user
917 * passes invalid parameters to a GL function.
918 *
919 * If debugging is enabled (either at compile-time via the DEBUG macro, or
920 * run-time via the MESA_DEBUG environment variable), report the error with
921 * _mesa_debug().
922 *
923 * \param ctx the GL context.
924 * \param error the error value.
925 * \param fmtString printf() style format string, followed by optional args
926 */
927 void
928 _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
929 {
930 GLboolean do_output, do_log;
931 /* Ideally this would be set up by the caller, so that we had proper IDs
932 * per different message.
933 */
934 static GLuint error_msg_id = 0;
935
936 debug_get_id(&error_msg_id);
937
938 do_output = should_output(ctx, error, fmtString);
939 do_log = should_log(ctx,
940 MESA_DEBUG_SOURCE_API,
941 MESA_DEBUG_TYPE_ERROR,
942 error_msg_id,
943 MESA_DEBUG_SEVERITY_HIGH);
944
945 if (do_output || do_log) {
946 char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
947 int len;
948 va_list args;
949
950 va_start(args, fmtString);
951 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
952 va_end(args);
953
954 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
955 /* Too long error message. Whoever calls _mesa_error should use
956 * shorter strings. */
957 ASSERT(0);
958 return;
959 }
960
961 len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
962 _mesa_lookup_enum_by_nr(error), s);
963 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
964 /* Same as above. */
965 ASSERT(0);
966 return;
967 }
968
969 /* Print the error to stderr if needed. */
970 if (do_output) {
971 output_if_debug("Mesa: User error", s2, GL_TRUE);
972 }
973
974 /* Log the error via ARB_debug_output if needed.*/
975 if (do_log) {
976 _mesa_log_msg(ctx,
977 MESA_DEBUG_SOURCE_API,
978 MESA_DEBUG_TYPE_ERROR,
979 error_msg_id,
980 MESA_DEBUG_SEVERITY_HIGH, len, s2);
981 }
982 }
983
984 /* Set the GL context error state for glGetError. */
985 _mesa_record_error(ctx, error);
986 }
987
988
989 /**
990 * Report debug information. Print error message to stderr via fprintf().
991 * No-op if DEBUG mode not enabled.
992 *
993 * \param ctx GL context.
994 * \param fmtString printf()-style format string, followed by optional args.
995 */
996 void
997 _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
998 {
999 #ifdef DEBUG
1000 char s[MAX_DEBUG_MESSAGE_LENGTH];
1001 va_list args;
1002 va_start(args, fmtString);
1003 _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
1004 va_end(args);
1005 output_if_debug("Mesa", s, GL_FALSE);
1006 #endif /* DEBUG */
1007 (void) ctx;
1008 (void) fmtString;
1009 }
1010
1011
1012 /**
1013 * Report debug information from the shader compiler via GL_ARB_debug_output.
1014 *
1015 * \param ctx GL context.
1016 * \param type The namespace to which this message belongs.
1017 * \param id The message ID within the given namespace.
1018 * \param msg The message to output. Need not be null-terminated.
1019 * \param len The length of 'msg'. If negative, 'msg' must be null-terminated.
1020 */
1021 void
1022 _mesa_shader_debug( struct gl_context *ctx, GLenum type, GLuint *id,
1023 const char *msg, int len )
1024 {
1025 enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
1026 enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH;
1027
1028 debug_get_id(id);
1029
1030 if (len < 0)
1031 len = strlen(msg);
1032
1033 /* Truncate the message if necessary. */
1034 if (len >= MAX_DEBUG_MESSAGE_LENGTH)
1035 len = MAX_DEBUG_MESSAGE_LENGTH - 1;
1036
1037 _mesa_log_msg(ctx, source, type, *id, severity, len, msg);
1038 }
1039
1040 /*@}*/