mesa: Fix assertion error with glDebugMessageControl
[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 for (i = 0; i < count; i++)
613 set_message_state(ctx, source, type, ids[i], enabled);
614
615 if (count)
616 return;
617
618 control_messages(ctx, source, type, severity, enabled);
619 }
620
621 void GLAPIENTRY
622 _mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type,
623 GLenum gl_severity,
624 GLsizei count, const GLuint *ids,
625 GLboolean enabled)
626 {
627 GET_CURRENT_CONTEXT(ctx);
628
629 if (count < 0) {
630 _mesa_error(ctx, GL_INVALID_VALUE, "glDebugMessageControlARB"
631 "(count=%d : count must not be negative)", count);
632 return;
633 }
634
635 if (!validate_params(ctx, CONTROL, gl_source, gl_type, gl_severity))
636 return; /* GL_INVALID_ENUM */
637
638 if (count && (gl_severity != GL_DONT_CARE || gl_type == GL_DONT_CARE
639 || gl_source == GL_DONT_CARE)) {
640 _mesa_error(ctx, GL_INVALID_OPERATION, "glDebugMessageControlARB"
641 "(When passing an array of ids, severity must be"
642 " GL_DONT_CARE, and source and type must not be GL_DONT_CARE.");
643 return;
644 }
645
646 control_app_messages(ctx, gl_source, gl_type, gl_severity,
647 count, ids, enabled);
648 }
649
650 void GLAPIENTRY
651 _mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, const void *userParam)
652 {
653 GET_CURRENT_CONTEXT(ctx);
654 ctx->Debug.Callback = callback;
655 ctx->Debug.CallbackData = userParam;
656 }
657
658 void
659 _mesa_init_errors(struct gl_context *ctx)
660 {
661 int s, t, sev;
662
663 ctx->Debug.Callback = NULL;
664 ctx->Debug.SyncOutput = GL_FALSE;
665 ctx->Debug.Log[0].length = 0;
666 ctx->Debug.NumMessages = 0;
667 ctx->Debug.NextMsg = 0;
668 ctx->Debug.NextMsgLength = 0;
669
670 /* Enable all the messages with severity HIGH or MEDIUM by default. */
671 memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH], GL_TRUE,
672 sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH]);
673 memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE,
674 sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM]);
675 memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW], GL_FALSE,
676 sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW]);
677
678 /* Initialize state for filtering known debug messages. */
679 for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
680 for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
681 ctx->Debug.Namespaces[s][t].IDs = _mesa_NewHashTable();
682 assert(ctx->Debug.Namespaces[s][t].IDs);
683
684 for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++)
685 make_empty_list(&ctx->Debug.Namespaces[s][t].Severity[sev]);
686 }
687 }
688
689 static void
690 do_nothing(GLuint key, void *data, void *userData)
691 {
692 }
693
694 void
695 _mesa_free_errors_data(struct gl_context *ctx)
696 {
697 enum mesa_debug_type t;
698 enum mesa_debug_source s;
699 enum mesa_debug_severity sev;
700
701 /* Tear down state for filtering debug messages. */
702 for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
703 for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
704 _mesa_HashDeleteAll(ctx->Debug.Namespaces[s][t].IDs, do_nothing, NULL);
705 _mesa_DeleteHashTable(ctx->Debug.Namespaces[s][t].IDs);
706 for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
707 struct simple_node *node, *tmp;
708 struct gl_debug_severity *entry;
709
710 foreach_s(node, tmp, &ctx->Debug.Namespaces[s][t].Severity[sev]) {
711 entry = (struct gl_debug_severity *)node;
712 free(entry);
713 }
714 }
715 }
716 }
717
718 /**********************************************************************/
719 /** \name Diagnostics */
720 /*@{*/
721
722 static void
723 output_if_debug(const char *prefixString, const char *outputString,
724 GLboolean newline)
725 {
726 static int debug = -1;
727 static FILE *fout = NULL;
728
729 /* Init the local 'debug' var once.
730 * Note: the _mesa_init_debug() function should have been called
731 * by now so MESA_DEBUG_FLAGS will be initialized.
732 */
733 if (debug == -1) {
734 /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
735 * etc to the named file. Otherwise, output to stderr.
736 */
737 const char *logFile = _mesa_getenv("MESA_LOG_FILE");
738 if (logFile)
739 fout = fopen(logFile, "w");
740 if (!fout)
741 fout = stderr;
742 #ifdef DEBUG
743 /* in debug builds, print messages unless MESA_DEBUG="silent" */
744 if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
745 debug = 0;
746 else
747 debug = 1;
748 #else
749 /* in release builds, be silent unless MESA_DEBUG is set */
750 debug = _mesa_getenv("MESA_DEBUG") != NULL;
751 #endif
752 }
753
754 /* Now only print the string if we're required to do so. */
755 if (debug) {
756 fprintf(fout, "%s: %s", prefixString, outputString);
757 if (newline)
758 fprintf(fout, "\n");
759 fflush(fout);
760
761 #if defined(_WIN32) && !defined(_WIN32_WCE)
762 /* stderr from windows applications without console is not usually
763 * visible, so communicate with the debugger instead */
764 {
765 char buf[4096];
766 _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
767 OutputDebugStringA(buf);
768 }
769 #endif
770 }
771 }
772
773 /**
774 * When a new type of error is recorded, print a message describing
775 * previous errors which were accumulated.
776 */
777 static void
778 flush_delayed_errors( struct gl_context *ctx )
779 {
780 char s[MAX_DEBUG_MESSAGE_LENGTH];
781
782 if (ctx->ErrorDebugCount) {
783 _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors",
784 ctx->ErrorDebugCount,
785 _mesa_lookup_enum_by_nr(ctx->ErrorValue));
786
787 output_if_debug("Mesa", s, GL_TRUE);
788
789 ctx->ErrorDebugCount = 0;
790 }
791 }
792
793
794 /**
795 * Report a warning (a recoverable error condition) to stderr if
796 * either DEBUG is defined or the MESA_DEBUG env var is set.
797 *
798 * \param ctx GL context.
799 * \param fmtString printf()-like format string.
800 */
801 void
802 _mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
803 {
804 char str[MAX_DEBUG_MESSAGE_LENGTH];
805 va_list args;
806 va_start( args, fmtString );
807 (void) _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
808 va_end( args );
809
810 if (ctx)
811 flush_delayed_errors( ctx );
812
813 output_if_debug("Mesa warning", str, GL_TRUE);
814 }
815
816
817 /**
818 * Report an internal implementation problem.
819 * Prints the message to stderr via fprintf().
820 *
821 * \param ctx GL context.
822 * \param fmtString problem description string.
823 */
824 void
825 _mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
826 {
827 va_list args;
828 char str[MAX_DEBUG_MESSAGE_LENGTH];
829 static int numCalls = 0;
830
831 (void) ctx;
832
833 if (numCalls < 50) {
834 numCalls++;
835
836 va_start( args, fmtString );
837 _mesa_vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args );
838 va_end( args );
839 fprintf(stderr, "Mesa %s implementation error: %s\n",
840 PACKAGE_VERSION, str);
841 fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n");
842 }
843 }
844
845 static GLboolean
846 should_output(struct gl_context *ctx, GLenum error, const char *fmtString)
847 {
848 static GLint debug = -1;
849
850 /* Check debug environment variable only once:
851 */
852 if (debug == -1) {
853 const char *debugEnv = _mesa_getenv("MESA_DEBUG");
854
855 #ifdef DEBUG
856 if (debugEnv && strstr(debugEnv, "silent"))
857 debug = GL_FALSE;
858 else
859 debug = GL_TRUE;
860 #else
861 if (debugEnv)
862 debug = GL_TRUE;
863 else
864 debug = GL_FALSE;
865 #endif
866 }
867
868 if (debug) {
869 if (ctx->ErrorValue != error ||
870 ctx->ErrorDebugFmtString != fmtString) {
871 flush_delayed_errors( ctx );
872 ctx->ErrorDebugFmtString = fmtString;
873 ctx->ErrorDebugCount = 0;
874 return GL_TRUE;
875 }
876 ctx->ErrorDebugCount++;
877 }
878 return GL_FALSE;
879 }
880
881 void
882 _mesa_gl_debug(struct gl_context *ctx,
883 GLuint *id,
884 enum mesa_debug_type type,
885 enum mesa_debug_severity severity,
886 const char *fmtString, ...)
887 {
888 char s[MAX_DEBUG_MESSAGE_LENGTH];
889 int len;
890 va_list args;
891
892 debug_get_id(id);
893
894 va_start(args, fmtString);
895 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
896 va_end(args);
897
898 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, type,
899 *id, severity, len, s);
900 }
901
902
903 /**
904 * Record an OpenGL state error. These usually occur when the user
905 * passes invalid parameters to a GL function.
906 *
907 * If debugging is enabled (either at compile-time via the DEBUG macro, or
908 * run-time via the MESA_DEBUG environment variable), report the error with
909 * _mesa_debug().
910 *
911 * \param ctx the GL context.
912 * \param error the error value.
913 * \param fmtString printf() style format string, followed by optional args
914 */
915 void
916 _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
917 {
918 GLboolean do_output, do_log;
919 /* Ideally this would be set up by the caller, so that we had proper IDs
920 * per different message.
921 */
922 static GLuint error_msg_id = 0;
923
924 debug_get_id(&error_msg_id);
925
926 do_output = should_output(ctx, error, fmtString);
927 do_log = should_log(ctx,
928 MESA_DEBUG_SOURCE_API,
929 MESA_DEBUG_TYPE_ERROR,
930 error_msg_id,
931 MESA_DEBUG_SEVERITY_HIGH);
932
933 if (do_output || do_log) {
934 char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
935 int len;
936 va_list args;
937
938 va_start(args, fmtString);
939 len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
940 va_end(args);
941
942 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
943 /* Too long error message. Whoever calls _mesa_error should use
944 * shorter strings. */
945 ASSERT(0);
946 return;
947 }
948
949 len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
950 _mesa_lookup_enum_by_nr(error), s);
951 if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
952 /* Same as above. */
953 ASSERT(0);
954 return;
955 }
956
957 /* Print the error to stderr if needed. */
958 if (do_output) {
959 output_if_debug("Mesa: User error", s2, GL_TRUE);
960 }
961
962 /* Log the error via ARB_debug_output if needed.*/
963 if (do_log) {
964 _mesa_log_msg(ctx,
965 MESA_DEBUG_SOURCE_API,
966 MESA_DEBUG_TYPE_ERROR,
967 error_msg_id,
968 MESA_DEBUG_SEVERITY_HIGH, len, s2);
969 }
970 }
971
972 /* Set the GL context error state for glGetError. */
973 _mesa_record_error(ctx, error);
974 }
975
976
977 /**
978 * Report debug information. Print error message to stderr via fprintf().
979 * No-op if DEBUG mode not enabled.
980 *
981 * \param ctx GL context.
982 * \param fmtString printf()-style format string, followed by optional args.
983 */
984 void
985 _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
986 {
987 #ifdef DEBUG
988 char s[MAX_DEBUG_MESSAGE_LENGTH];
989 va_list args;
990 va_start(args, fmtString);
991 _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
992 va_end(args);
993 output_if_debug("Mesa", s, GL_FALSE);
994 #endif /* DEBUG */
995 (void) ctx;
996 (void) fmtString;
997 }
998
999
1000 /**
1001 * Report debug information from the shader compiler via GL_ARB_debug_output.
1002 *
1003 * \param ctx GL context.
1004 * \param type The namespace to which this message belongs.
1005 * \param id The message ID within the given namespace.
1006 * \param msg The message to output. Need not be null-terminated.
1007 * \param len The length of 'msg'. If negative, 'msg' must be null-terminated.
1008 */
1009 void
1010 _mesa_shader_debug( struct gl_context *ctx, GLenum type, GLuint *id,
1011 const char *msg, int len )
1012 {
1013 enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER;
1014 enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH;
1015
1016 debug_get_id(id);
1017
1018 if (len < 0)
1019 len = strlen(msg);
1020
1021 /* Truncate the message if necessary. */
1022 if (len >= MAX_DEBUG_MESSAGE_LENGTH)
1023 len = MAX_DEBUG_MESSAGE_LENGTH - 1;
1024
1025 _mesa_log_msg(ctx, source, type, *id, severity, len, msg);
1026 }
1027
1028 /*@}*/