diff --git a/docs/envvars.rst b/docs/envvars.rst index 2a756f8d94f..72852ef8cf8 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -81,6 +81,10 @@ Core Mesa environment variables purposes (e.g. for driconf option matching, logging, artifact storage, etc.). +.. envvar:: MESA_LOG_LEVEL + + specifies the maximum log level + .. envvar:: MESA_LOG_FILE specifies a file name for logging all errors, warnings, etc., rather diff --git a/src/util/log.c b/src/util/log.c index 35c55ba8ce6..39cba6ecdaa 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -67,8 +67,35 @@ static const struct debug_control mesa_log_control_options[] = { { NULL, 0 }, }; +static inline const char * +level_to_str(enum mesa_log_level l) +{ + switch (l) { + case MESA_LOG_ERROR: return "error"; + case MESA_LOG_WARN: return "warning"; + case MESA_LOG_INFO: return "info"; + case MESA_LOG_DEBUG: return "debug"; + case MESA_NUM_LOG_LEVELS: + break; + } + + UNREACHABLE("bad mesa_log_level"); +} + +static enum mesa_log_level +level_from_str(const char *str) +{ + for (unsigned l = 0; l < MESA_NUM_LOG_LEVELS; l++) { + if (strcmp(level_to_str(l), str) == 0) + return l; + } + + return MESA_NUM_LOG_LEVELS; +} + static uint32_t mesa_log_control; static FILE *mesa_log_file; +static enum mesa_log_level mesa_max_log_level; static void mesa_log_init_once(void) @@ -91,6 +118,11 @@ mesa_log_init_once(void) #endif } + mesa_max_log_level = MESA_DEFAULT_LOG_LEVEL; + const char *log_level = os_get_option("MESA_LOG_LEVEL"); + if (log_level != NULL) + mesa_max_log_level = level_from_str(log_level); + mesa_log_file = stderr; #if !DETECT_OS_WINDOWS @@ -119,6 +151,20 @@ mesa_log_init(void) call_once(&once, mesa_log_init_once); } +static void +mesa_warn_invalid_level_once(void) +{ + const char *log_level = os_get_option("MESA_LOG_LEVEL"); + mesa_logw("Invalid log level: \"%s\"", log_level); +} + +static void +mesa_warn_invalid_level(void) +{ + static once_flag once = ONCE_FLAG_INIT; + call_once(&once, mesa_warn_invalid_level_once); +} + void mesa_log_if_debug(enum mesa_log_level level, const char *outputString) { @@ -147,19 +193,6 @@ mesa_log_if_debug(enum mesa_log_level level, const char *outputString) mesa_log(level, "Mesa", "%s", outputString); } -static inline const char * -level_to_str(enum mesa_log_level l) -{ - switch (l) { - case MESA_LOG_ERROR: return "error"; - case MESA_LOG_WARN: return "warning"; - case MESA_LOG_INFO: return "info"; - case MESA_LOG_DEBUG: return "debug"; - } - - UNREACHABLE("bad mesa_log_level"); -} - enum logger_vasnprintf_affix { LOGGER_VASNPRINTF_AFFIX_TAG = 1 << 0, LOGGER_VASNPRINTF_AFFIX_LEVEL = 1 << 1, @@ -270,6 +303,8 @@ level_to_syslog(enum mesa_log_level l) case MESA_LOG_WARN: return LOG_WARNING; case MESA_LOG_INFO: return LOG_INFO; case MESA_LOG_DEBUG: return LOG_DEBUG; + case MESA_NUM_LOG_LEVELS: + break; } UNREACHABLE("bad mesa_log_level"); @@ -303,6 +338,8 @@ level_to_android(enum mesa_log_level l) case MESA_LOG_WARN: return ANDROID_LOG_WARN; case MESA_LOG_INFO: return ANDROID_LOG_INFO; case MESA_LOG_DEBUG: return ANDROID_LOG_DEBUG; + case MESA_NUM_LOG_LEVELS: + break; } UNREACHABLE("bad mesa_log_level"); @@ -405,6 +442,17 @@ mesa_log_v(enum mesa_log_level level, const char *tag, const char *format, mesa_log_init(); + if (unlikely(mesa_max_log_level >= MESA_NUM_LOG_LEVELS)) { + /* Set to the default since this function will call back into mesa_log() + * and we don't want to recurse back into the once. + */ + mesa_max_log_level = MESA_DEFAULT_LOG_LEVEL; + mesa_warn_invalid_level(); + } + + if (level > mesa_max_log_level) + return; + for (uint32_t i = 0; i < ARRAY_SIZE(loggers); i++) { if (mesa_log_control & loggers[i].bit) { va_list copy; diff --git a/src/util/log.h b/src/util/log.h index 7bcce3d61e0..c1d9f806232 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -42,8 +42,16 @@ enum mesa_log_level { MESA_LOG_WARN, MESA_LOG_INFO, MESA_LOG_DEBUG, + + MESA_NUM_LOG_LEVELS, }; +#if MESA_DEBUG +#define MESA_DEFAULT_LOG_LEVEL MESA_LOG_DEBUG +#else +#define MESA_DEFAULT_LOG_LEVEL MESA_LOG_INFO +#endif + #define MAX_LOG_MESSAGE_LENGTH 4096 FILE *