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