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