1bf215546Sopenharmony_ci/** 2bf215546Sopenharmony_ci * \file errors.c 3bf215546Sopenharmony_ci * Mesa debugging and error handling functions. 4bf215546Sopenharmony_ci */ 5bf215546Sopenharmony_ci 6bf215546Sopenharmony_ci/* 7bf215546Sopenharmony_ci * Mesa 3-D graphics library 8bf215546Sopenharmony_ci * 9bf215546Sopenharmony_ci * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 12bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 13bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 14bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 16bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 19bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 20bf215546Sopenharmony_ci * 21bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include <stdarg.h> 32bf215546Sopenharmony_ci#include <stdio.h> 33bf215546Sopenharmony_ci#include "errors.h" 34bf215546Sopenharmony_ci#include "enums.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "context.h" 37bf215546Sopenharmony_ci#include "debug_output.h" 38bf215546Sopenharmony_ci#include "detect_os.h" 39bf215546Sopenharmony_ci#include "api_exec_decl.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#if DETECT_OS_ANDROID 42bf215546Sopenharmony_ci# include <log/log.h> 43bf215546Sopenharmony_ci#endif 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistatic FILE *LogFile = NULL; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic void 49bf215546Sopenharmony_cioutput_if_debug(const char *prefixString, const char *outputString, 50bf215546Sopenharmony_ci GLboolean newline) 51bf215546Sopenharmony_ci{ 52bf215546Sopenharmony_ci static int debug = -1; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci /* Init the local 'debug' var once. 55bf215546Sopenharmony_ci * Note: the _mesa_init_debug() function should have been called 56bf215546Sopenharmony_ci * by now so MESA_DEBUG_FLAGS will be initialized. 57bf215546Sopenharmony_ci */ 58bf215546Sopenharmony_ci if (debug == -1) { 59bf215546Sopenharmony_ci /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings, 60bf215546Sopenharmony_ci * etc to the named file. Otherwise, output to stderr. 61bf215546Sopenharmony_ci */ 62bf215546Sopenharmony_ci const char *logFile = getenv("MESA_LOG_FILE"); 63bf215546Sopenharmony_ci if (logFile) 64bf215546Sopenharmony_ci LogFile = fopen(logFile, "w"); 65bf215546Sopenharmony_ci if (!LogFile) 66bf215546Sopenharmony_ci LogFile = stderr; 67bf215546Sopenharmony_ci#ifndef NDEBUG 68bf215546Sopenharmony_ci /* in debug builds, print messages unless MESA_DEBUG="silent" */ 69bf215546Sopenharmony_ci if (MESA_DEBUG_FLAGS & DEBUG_SILENT) 70bf215546Sopenharmony_ci debug = 0; 71bf215546Sopenharmony_ci else 72bf215546Sopenharmony_ci debug = 1; 73bf215546Sopenharmony_ci#else 74bf215546Sopenharmony_ci const char *env = getenv("MESA_DEBUG"); 75bf215546Sopenharmony_ci debug = env && strstr(env, "silent") == NULL; 76bf215546Sopenharmony_ci#endif 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci /* Now only print the string if we're required to do so. */ 80bf215546Sopenharmony_ci if (debug) { 81bf215546Sopenharmony_ci if (prefixString) 82bf215546Sopenharmony_ci fprintf(LogFile, "%s: %s", prefixString, outputString); 83bf215546Sopenharmony_ci else 84bf215546Sopenharmony_ci fprintf(LogFile, "%s", outputString); 85bf215546Sopenharmony_ci if (newline) 86bf215546Sopenharmony_ci fprintf(LogFile, "\n"); 87bf215546Sopenharmony_ci fflush(LogFile); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci#if defined(_WIN32) 90bf215546Sopenharmony_ci /* stderr from windows applications without console is not usually 91bf215546Sopenharmony_ci * visible, so communicate with the debugger instead */ 92bf215546Sopenharmony_ci { 93bf215546Sopenharmony_ci char buf[4096]; 94bf215546Sopenharmony_ci if (prefixString) 95bf215546Sopenharmony_ci snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : ""); 96bf215546Sopenharmony_ci else 97bf215546Sopenharmony_ci snprintf(buf, sizeof(buf), "%s%s", outputString, newline ? "\n" : ""); 98bf215546Sopenharmony_ci OutputDebugStringA(buf); 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci#endif 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci#if DETECT_OS_ANDROID 103bf215546Sopenharmony_ci LOG_PRI(ANDROID_LOG_ERROR, prefixString ? prefixString : "MESA", "%s%s", outputString, newline ? "\n" : ""); 104bf215546Sopenharmony_ci#endif 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci/** 110bf215546Sopenharmony_ci * Return the file handle to use for debug/logging. Defaults to stderr 111bf215546Sopenharmony_ci * unless MESA_LOG_FILE is defined. 112bf215546Sopenharmony_ci */ 113bf215546Sopenharmony_ciFILE * 114bf215546Sopenharmony_ci_mesa_get_log_file(void) 115bf215546Sopenharmony_ci{ 116bf215546Sopenharmony_ci assert(LogFile); 117bf215546Sopenharmony_ci return LogFile; 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci/** 122bf215546Sopenharmony_ci * When a new type of error is recorded, print a message describing 123bf215546Sopenharmony_ci * previous errors which were accumulated. 124bf215546Sopenharmony_ci */ 125bf215546Sopenharmony_cistatic void 126bf215546Sopenharmony_ciflush_delayed_errors( struct gl_context *ctx ) 127bf215546Sopenharmony_ci{ 128bf215546Sopenharmony_ci char s[MAX_DEBUG_MESSAGE_LENGTH]; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci if (ctx->ErrorDebugCount) { 131bf215546Sopenharmony_ci snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors", 132bf215546Sopenharmony_ci ctx->ErrorDebugCount, 133bf215546Sopenharmony_ci _mesa_enum_to_string(ctx->ErrorValue)); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci output_if_debug("Mesa", s, GL_TRUE); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci ctx->ErrorDebugCount = 0; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci} 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci/** 143bf215546Sopenharmony_ci * Report a warning (a recoverable error condition) to stderr if 144bf215546Sopenharmony_ci * either DEBUG is defined or the MESA_DEBUG env var is set. 145bf215546Sopenharmony_ci * 146bf215546Sopenharmony_ci * \param ctx GL context. 147bf215546Sopenharmony_ci * \param fmtString printf()-like format string. 148bf215546Sopenharmony_ci */ 149bf215546Sopenharmony_civoid 150bf215546Sopenharmony_ci_mesa_warning( struct gl_context *ctx, const char *fmtString, ... ) 151bf215546Sopenharmony_ci{ 152bf215546Sopenharmony_ci char str[MAX_DEBUG_MESSAGE_LENGTH]; 153bf215546Sopenharmony_ci va_list args; 154bf215546Sopenharmony_ci va_start( args, fmtString ); 155bf215546Sopenharmony_ci (void) vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args ); 156bf215546Sopenharmony_ci va_end( args ); 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci if (ctx) 159bf215546Sopenharmony_ci flush_delayed_errors( ctx ); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci output_if_debug("Mesa warning", str, GL_TRUE); 162bf215546Sopenharmony_ci} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci/** 166bf215546Sopenharmony_ci * Report an internal implementation problem. 167bf215546Sopenharmony_ci * Prints the message to stderr via fprintf(). 168bf215546Sopenharmony_ci * 169bf215546Sopenharmony_ci * \param ctx GL context. 170bf215546Sopenharmony_ci * \param fmtString problem description string. 171bf215546Sopenharmony_ci */ 172bf215546Sopenharmony_civoid 173bf215546Sopenharmony_ci_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci va_list args; 176bf215546Sopenharmony_ci char str[MAX_DEBUG_MESSAGE_LENGTH]; 177bf215546Sopenharmony_ci static int numCalls = 0; 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci (void) ctx; 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci if (numCalls < 50) { 182bf215546Sopenharmony_ci numCalls++; 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci va_start( args, fmtString ); 185bf215546Sopenharmony_ci vsnprintf( str, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args ); 186bf215546Sopenharmony_ci va_end( args ); 187bf215546Sopenharmony_ci fprintf(stderr, "Mesa " PACKAGE_VERSION " implementation error: %s\n", 188bf215546Sopenharmony_ci str); 189bf215546Sopenharmony_ci fprintf(stderr, "Please report at " PACKAGE_BUGREPORT "\n"); 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci} 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_cistatic GLboolean 195bf215546Sopenharmony_cishould_output(struct gl_context *ctx, GLenum error, const char *fmtString) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci static GLint debug = -1; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci /* Check debug environment variable only once: 200bf215546Sopenharmony_ci */ 201bf215546Sopenharmony_ci if (debug == -1) { 202bf215546Sopenharmony_ci const char *debugEnv = getenv("MESA_DEBUG"); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci#ifndef NDEBUG 205bf215546Sopenharmony_ci if (debugEnv && strstr(debugEnv, "silent")) 206bf215546Sopenharmony_ci debug = GL_FALSE; 207bf215546Sopenharmony_ci else 208bf215546Sopenharmony_ci debug = GL_TRUE; 209bf215546Sopenharmony_ci#else 210bf215546Sopenharmony_ci if (debugEnv) 211bf215546Sopenharmony_ci debug = GL_TRUE; 212bf215546Sopenharmony_ci else 213bf215546Sopenharmony_ci debug = GL_FALSE; 214bf215546Sopenharmony_ci#endif 215bf215546Sopenharmony_ci } 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci if (debug) { 218bf215546Sopenharmony_ci if (ctx->ErrorValue != error || 219bf215546Sopenharmony_ci ctx->ErrorDebugFmtString != fmtString) { 220bf215546Sopenharmony_ci flush_delayed_errors( ctx ); 221bf215546Sopenharmony_ci ctx->ErrorDebugFmtString = fmtString; 222bf215546Sopenharmony_ci ctx->ErrorDebugCount = 0; 223bf215546Sopenharmony_ci return GL_TRUE; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci ctx->ErrorDebugCount++; 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci return GL_FALSE; 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_civoid 232bf215546Sopenharmony_ci_mesa_gl_vdebugf(struct gl_context *ctx, 233bf215546Sopenharmony_ci GLuint *id, 234bf215546Sopenharmony_ci enum mesa_debug_source source, 235bf215546Sopenharmony_ci enum mesa_debug_type type, 236bf215546Sopenharmony_ci enum mesa_debug_severity severity, 237bf215546Sopenharmony_ci const char *fmtString, 238bf215546Sopenharmony_ci va_list args) 239bf215546Sopenharmony_ci{ 240bf215546Sopenharmony_ci char s[MAX_DEBUG_MESSAGE_LENGTH]; 241bf215546Sopenharmony_ci int len; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci _mesa_debug_get_id(id); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci len = vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); 246bf215546Sopenharmony_ci if (len >= MAX_DEBUG_MESSAGE_LENGTH) 247bf215546Sopenharmony_ci /* message was truncated */ 248bf215546Sopenharmony_ci len = MAX_DEBUG_MESSAGE_LENGTH - 1; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci _mesa_log_msg(ctx, source, type, *id, severity, len, s); 251bf215546Sopenharmony_ci} 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_civoid 255bf215546Sopenharmony_ci_mesa_gl_debugf(struct gl_context *ctx, 256bf215546Sopenharmony_ci GLuint *id, 257bf215546Sopenharmony_ci enum mesa_debug_source source, 258bf215546Sopenharmony_ci enum mesa_debug_type type, 259bf215546Sopenharmony_ci enum mesa_debug_severity severity, 260bf215546Sopenharmony_ci const char *fmtString, ...) 261bf215546Sopenharmony_ci{ 262bf215546Sopenharmony_ci va_list args; 263bf215546Sopenharmony_ci va_start(args, fmtString); 264bf215546Sopenharmony_ci _mesa_gl_vdebugf(ctx, id, source, type, severity, fmtString, args); 265bf215546Sopenharmony_ci va_end(args); 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_cisize_t 269bf215546Sopenharmony_ci_mesa_gl_debug(struct gl_context *ctx, 270bf215546Sopenharmony_ci GLuint *id, 271bf215546Sopenharmony_ci enum mesa_debug_source source, 272bf215546Sopenharmony_ci enum mesa_debug_type type, 273bf215546Sopenharmony_ci enum mesa_debug_severity severity, 274bf215546Sopenharmony_ci const char *msg) 275bf215546Sopenharmony_ci{ 276bf215546Sopenharmony_ci _mesa_debug_get_id(id); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci size_t len = strnlen(msg, MAX_DEBUG_MESSAGE_LENGTH); 279bf215546Sopenharmony_ci if (len < MAX_DEBUG_MESSAGE_LENGTH) { 280bf215546Sopenharmony_ci _mesa_log_msg(ctx, source, type, *id, severity, len, msg); 281bf215546Sopenharmony_ci return len; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci /* limit the message to fit within KHR_debug buffers */ 285bf215546Sopenharmony_ci char s[MAX_DEBUG_MESSAGE_LENGTH]; 286bf215546Sopenharmony_ci strncpy(s, msg, MAX_DEBUG_MESSAGE_LENGTH); 287bf215546Sopenharmony_ci s[MAX_DEBUG_MESSAGE_LENGTH - 1] = '\0'; 288bf215546Sopenharmony_ci len = MAX_DEBUG_MESSAGE_LENGTH - 1; 289bf215546Sopenharmony_ci _mesa_log_msg(ctx, source, type, *id, severity, len, s); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci /* report the number of characters that were logged */ 292bf215546Sopenharmony_ci return len; 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci/** 297bf215546Sopenharmony_ci * Record an OpenGL state error. These usually occur when the user 298bf215546Sopenharmony_ci * passes invalid parameters to a GL function. 299bf215546Sopenharmony_ci * 300bf215546Sopenharmony_ci * If debugging is enabled (either at compile-time via the DEBUG macro, or 301bf215546Sopenharmony_ci * run-time via the MESA_DEBUG environment variable), report the error with 302bf215546Sopenharmony_ci * _mesa_debug(). 303bf215546Sopenharmony_ci * 304bf215546Sopenharmony_ci * \param ctx the GL context. 305bf215546Sopenharmony_ci * \param error the error value. 306bf215546Sopenharmony_ci * \param fmtString printf() style format string, followed by optional args 307bf215546Sopenharmony_ci */ 308bf215546Sopenharmony_civoid 309bf215546Sopenharmony_ci_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci GLboolean do_output, do_log; 312bf215546Sopenharmony_ci /* Ideally this would be set up by the caller, so that we had proper IDs 313bf215546Sopenharmony_ci * per different message. 314bf215546Sopenharmony_ci */ 315bf215546Sopenharmony_ci static GLuint error_msg_id = 0; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci _mesa_debug_get_id(&error_msg_id); 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci do_output = should_output(ctx, error, fmtString); 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci simple_mtx_lock(&ctx->DebugMutex); 322bf215546Sopenharmony_ci if (ctx->Debug) { 323bf215546Sopenharmony_ci do_log = _mesa_debug_is_message_enabled(ctx->Debug, 324bf215546Sopenharmony_ci MESA_DEBUG_SOURCE_API, 325bf215546Sopenharmony_ci MESA_DEBUG_TYPE_ERROR, 326bf215546Sopenharmony_ci error_msg_id, 327bf215546Sopenharmony_ci MESA_DEBUG_SEVERITY_HIGH); 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci else { 330bf215546Sopenharmony_ci do_log = GL_FALSE; 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci simple_mtx_unlock(&ctx->DebugMutex); 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if (do_output || do_log) { 335bf215546Sopenharmony_ci char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH]; 336bf215546Sopenharmony_ci int len; 337bf215546Sopenharmony_ci va_list args; 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci va_start(args, fmtString); 340bf215546Sopenharmony_ci len = vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); 341bf215546Sopenharmony_ci va_end(args); 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci if (len >= MAX_DEBUG_MESSAGE_LENGTH) { 344bf215546Sopenharmony_ci /* Too long error message. Whoever calls _mesa_error should use 345bf215546Sopenharmony_ci * shorter strings. 346bf215546Sopenharmony_ci */ 347bf215546Sopenharmony_ci assert(0); 348bf215546Sopenharmony_ci return; 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci len = snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s", 352bf215546Sopenharmony_ci _mesa_enum_to_string(error), s); 353bf215546Sopenharmony_ci if (len >= MAX_DEBUG_MESSAGE_LENGTH) { 354bf215546Sopenharmony_ci /* Same as above. */ 355bf215546Sopenharmony_ci assert(0); 356bf215546Sopenharmony_ci return; 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci /* Print the error to stderr if needed. */ 360bf215546Sopenharmony_ci if (do_output) { 361bf215546Sopenharmony_ci output_if_debug("Mesa: User error", s2, GL_TRUE); 362bf215546Sopenharmony_ci } 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci /* Log the error via ARB_debug_output if needed.*/ 365bf215546Sopenharmony_ci if (do_log) { 366bf215546Sopenharmony_ci _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_ERROR, 367bf215546Sopenharmony_ci error_msg_id, MESA_DEBUG_SEVERITY_HIGH, len, s2); 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci /* Set the GL context error state for glGetError. */ 372bf215546Sopenharmony_ci if (ctx->ErrorValue == GL_NO_ERROR) 373bf215546Sopenharmony_ci ctx->ErrorValue = error; 374bf215546Sopenharmony_ci} 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_civoid 377bf215546Sopenharmony_ci_mesa_error_no_memory(const char *caller) 378bf215546Sopenharmony_ci{ 379bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 380bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "out of memory in %s", caller); 381bf215546Sopenharmony_ci} 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci/** 384bf215546Sopenharmony_ci * Report debug information. Print error message to stderr via fprintf(). 385bf215546Sopenharmony_ci * No-op if DEBUG mode not enabled. 386bf215546Sopenharmony_ci * 387bf215546Sopenharmony_ci * \param ctx GL context. 388bf215546Sopenharmony_ci * \param fmtString printf()-style format string, followed by optional args. 389bf215546Sopenharmony_ci */ 390bf215546Sopenharmony_civoid 391bf215546Sopenharmony_ci_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) 392bf215546Sopenharmony_ci{ 393bf215546Sopenharmony_ci#ifndef NDEBUG 394bf215546Sopenharmony_ci char s[MAX_DEBUG_MESSAGE_LENGTH]; 395bf215546Sopenharmony_ci va_list args; 396bf215546Sopenharmony_ci va_start(args, fmtString); 397bf215546Sopenharmony_ci vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); 398bf215546Sopenharmony_ci va_end(args); 399bf215546Sopenharmony_ci output_if_debug("Mesa", s, GL_FALSE); 400bf215546Sopenharmony_ci#endif /* DEBUG */ 401bf215546Sopenharmony_ci (void) ctx; 402bf215546Sopenharmony_ci (void) fmtString; 403bf215546Sopenharmony_ci} 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_civoid 407bf215546Sopenharmony_ci_mesa_log(const char *fmtString, ...) 408bf215546Sopenharmony_ci{ 409bf215546Sopenharmony_ci char s[MAX_DEBUG_MESSAGE_LENGTH]; 410bf215546Sopenharmony_ci va_list args; 411bf215546Sopenharmony_ci va_start(args, fmtString); 412bf215546Sopenharmony_ci vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args); 413bf215546Sopenharmony_ci va_end(args); 414bf215546Sopenharmony_ci output_if_debug(NULL, s, GL_FALSE); 415bf215546Sopenharmony_ci} 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_civoid 418bf215546Sopenharmony_ci_mesa_log_direct(const char *string) 419bf215546Sopenharmony_ci{ 420bf215546Sopenharmony_ci output_if_debug(NULL, string, GL_TRUE); 421bf215546Sopenharmony_ci} 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci/** 424bf215546Sopenharmony_ci * Report debug information from the shader compiler via GL_ARB_debug_output. 425bf215546Sopenharmony_ci * 426bf215546Sopenharmony_ci * \param ctx GL context. 427bf215546Sopenharmony_ci * \param type The namespace to which this message belongs. 428bf215546Sopenharmony_ci * \param id The message ID within the given namespace. 429bf215546Sopenharmony_ci * \param msg The message to output. Must be null-terminated. 430bf215546Sopenharmony_ci */ 431bf215546Sopenharmony_civoid 432bf215546Sopenharmony_ci_mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id, 433bf215546Sopenharmony_ci const char *msg) 434bf215546Sopenharmony_ci{ 435bf215546Sopenharmony_ci enum mesa_debug_source source = MESA_DEBUG_SOURCE_SHADER_COMPILER; 436bf215546Sopenharmony_ci enum mesa_debug_severity severity = MESA_DEBUG_SEVERITY_HIGH; 437bf215546Sopenharmony_ci int len; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci _mesa_debug_get_id(id); 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci len = strlen(msg); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci /* Truncate the message if necessary. */ 444bf215546Sopenharmony_ci if (len >= MAX_DEBUG_MESSAGE_LENGTH) 445bf215546Sopenharmony_ci len = MAX_DEBUG_MESSAGE_LENGTH - 1; 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci _mesa_log_msg(ctx, source, type, *id, severity, len, msg); 448bf215546Sopenharmony_ci} 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci/** 451bf215546Sopenharmony_ci * Set the parameter as the current GL error. Used by glthread. 452bf215546Sopenharmony_ci */ 453bf215546Sopenharmony_civoid GLAPIENTRY 454bf215546Sopenharmony_ci_mesa_InternalSetError(GLenum error) 455bf215546Sopenharmony_ci{ 456bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 457bf215546Sopenharmony_ci _mesa_error(ctx, error, "glthread"); 458bf215546Sopenharmony_ci} 459