diff options
Diffstat (limited to 'src/egl/main/egllog.c')
| -rw-r--r-- | src/egl/main/egllog.c | 185 | 
1 files changed, 130 insertions, 55 deletions
| diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c index 1d7a0a388c..11a9bf7275 100644 --- a/src/egl/main/egllog.c +++ b/src/egl/main/egllog.c @@ -9,51 +9,140 @@  #include <stdio.h>  #include <stdlib.h>  #include <string.h> +  #include "egllog.h" +#include "eglmutex.h"  #define MAXSTRING 1000 -#define FALLBACK_LOG_LEVEL      _EGL_WARNING -#define FALLBACK_LOG_LEVEL_STR  "warning" +#define FALLBACK_LOG_LEVEL _EGL_WARNING -static EGLint ReportingLevel = -1; +static struct { +   _EGLMutex mutex; -static void -log_level_initialize(void) +   EGLBoolean initialized; +   EGLint level; +   _EGLLogProc logger; +   EGLint num_messages; +} logging = { +   _EGL_MUTEX_INITIALIZER, +   EGL_FALSE, +   FALLBACK_LOG_LEVEL, +   NULL, +   0 +}; + +static const char *level_strings[] = { +   /* the order is important */ +   "fatal", +   "warning", +   "info", +   "debug", +   NULL +}; + + +/** + * Set the function to be called when there is a message to log. + * Note that the function will be called with an internal lock held. + * Recursive logging is not allowed. + */ +void +_eglSetLogProc(_EGLLogProc logger)  { -#if defined(_EGL_PLATFORM_X)   -   char *log_env = getenv("EGL_LOG_LEVEL"); -#else -   char *log_env = NULL; -#endif +   EGLint num_messages = 0; -   if (log_env == NULL) { -      ReportingLevel = FALLBACK_LOG_LEVEL; -   } -   else if (strcasecmp(log_env, "fatal") == 0) { -      ReportingLevel = _EGL_FATAL; -   } -   else if (strcasecmp(log_env, "warning") == 0) { -      ReportingLevel = _EGL_WARNING; +   _eglLockMutex(&logging.mutex); + +   if (logging.logger != logger) { +      logging.logger = logger; + +      num_messages = logging.num_messages; +      logging.num_messages = 0;     } -   else if (strcasecmp(log_env, "info") == 0) { -      ReportingLevel = _EGL_INFO; + +   _eglUnlockMutex(&logging.mutex); + +   if (num_messages) +      _eglLog(_EGL_DEBUG, +              "New logger installed. " +              "Messages before the new logger might not be available."); +} + + +/** + * Set the log reporting level. + */ +void +_eglSetLogLevel(EGLint level) +{ +   switch (level) { +   case _EGL_FATAL: +   case _EGL_WARNING: +   case _EGL_INFO: +   case _EGL_DEBUG: +      _eglLockMutex(&logging.mutex); +      logging.level = level; +      _eglUnlockMutex(&logging.mutex); +      break; +   default: +      break;     } -   else if (strcasecmp(log_env, "debug") == 0) { -      ReportingLevel = _EGL_DEBUG; +} + + +/** + * The default logger.  It prints the message to stderr. + */ +static void +_eglDefaultLogger(EGLint level, const char *msg) +{ +   fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg); +} + + +/** + * Initialize the logging facility. + */ +static void +_eglInitLogger(void) +{ +   const char *log_env; +   EGLint i, level = -1; + +   if (logging.initialized) +      return; + +   log_env = getenv("EGL_LOG_LEVEL"); +   if (log_env) { +      for (i = 0; level_strings[i]; i++) { +         if (strcasecmp(log_env, level_strings[i]) == 0) { +            level = i; +            break; +         } +      }     }     else { -      fprintf(stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. " +      level = FALLBACK_LOG_LEVEL; +   } + +   logging.logger = _eglDefaultLogger; +   logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL; +   logging.initialized = EGL_TRUE; + +   /* it is fine to call _eglLog now */ +   if (log_env && level < 0) { +      _eglLog(_EGL_WARNING, +              "Unrecognized EGL_LOG_LEVEL environment variable value. "                "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". " -              "Got \"%s\". Falling back to \"%s\".\n", -              log_env, FALLBACK_LOG_LEVEL_STR); -      ReportingLevel = FALLBACK_LOG_LEVEL; +              "Got \"%s\". Falling back to \"%s\".", +              log_env, level_strings[FALLBACK_LOG_LEVEL]);     }  }  /** - * Log a message to stderr. + * Log a message with message logger.   * \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.   */  void @@ -61,40 +150,26 @@ _eglLog(EGLint level, const char *fmtStr, ...)  {     va_list args;     char msg[MAXSTRING]; -   const char *levelStr; -   static int log_level_initialized = 0; -   if (!log_level_initialized) { -      log_level_initialize(); -      log_level_initialized = 1; -   } +   /* one-time initialization; a little race here is fine */ +   if (!logging.initialized) +      _eglInitLogger(); +   if (level > logging.level || level < 0) +      return; -   if (level <= ReportingLevel) { -      switch (level) { -      case _EGL_FATAL: -         levelStr = "Fatal"; -         break; -      case _EGL_WARNING: -         levelStr = "Warning"; -         break; -      case _EGL_INFO: -         levelStr = "Info"; -         break; -      case _EGL_DEBUG: -         levelStr = "Debug"; -         break; -      default: -         levelStr = ""; -      } +   _eglLockMutex(&logging.mutex); +   if (logging.logger) {        va_start(args, fmtStr);        vsnprintf(msg, MAXSTRING, fmtStr, args);        va_end(args); -      fprintf(stderr, "libEGL %s: %s\n", levelStr, msg); - -      if (level == _EGL_FATAL) { -         exit(1); /* or abort()? */ -      } +      logging.logger(level, msg); +      logging.num_messages++;     } + +   _eglUnlockMutex(&logging.mutex); + +   if (level == _EGL_FATAL) +      exit(1); /* or abort()? */  } | 
