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