egl: Improve logging facility.
Add _eglSetLogger and _eglSetLogLevel to allow drivers to change the message logger or report level. Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
This commit is contained in:
@@ -18,9 +18,10 @@ struct _egl_global _eglGlobal =
|
|||||||
0, /* NumDrivers */
|
0, /* NumDrivers */
|
||||||
{ NULL }, /* Drivers */
|
{ NULL }, /* Drivers */
|
||||||
2, /* NumAtExitCalls */
|
2, /* NumAtExitCalls */
|
||||||
{ /* AtExitCalls */
|
{
|
||||||
_eglFiniDisplay,
|
/* default AtExitCalls, called in reverse order */
|
||||||
_eglUnloadDrivers
|
_eglUnloadDrivers, /* always called last */
|
||||||
|
_eglFiniDisplay
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -9,47 +9,140 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "egllog.h"
|
#include "egllog.h"
|
||||||
|
#include "eglmutex.h"
|
||||||
|
|
||||||
#define MAXSTRING 1000
|
#define MAXSTRING 1000
|
||||||
#define FALLBACK_LOG_LEVEL _EGL_WARNING
|
#define FALLBACK_LOG_LEVEL _EGL_WARNING
|
||||||
#define FALLBACK_LOG_LEVEL_STR "warning"
|
|
||||||
|
|
||||||
static EGLint ReportingLevel = -1;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static struct {
|
||||||
log_level_initialize(void)
|
_EGLMutex mutex;
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
char *log_env = getenv("EGL_LOG_LEVEL");
|
EGLint num_messages = 0;
|
||||||
|
|
||||||
if (log_env == NULL) {
|
_eglLockMutex(&logging.mutex);
|
||||||
ReportingLevel = FALLBACK_LOG_LEVEL;
|
|
||||||
|
if (logging.logger != logger) {
|
||||||
|
logging.logger = logger;
|
||||||
|
|
||||||
|
num_messages = logging.num_messages;
|
||||||
|
logging.num_messages = 0;
|
||||||
}
|
}
|
||||||
else if (strcasecmp(log_env, "fatal") == 0) {
|
|
||||||
ReportingLevel = _EGL_FATAL;
|
_eglUnlockMutex(&logging.mutex);
|
||||||
}
|
|
||||||
else if (strcasecmp(log_env, "warning") == 0) {
|
if (num_messages)
|
||||||
ReportingLevel = _EGL_WARNING;
|
_eglLog(_EGL_DEBUG,
|
||||||
}
|
"New logger installed. "
|
||||||
else if (strcasecmp(log_env, "info") == 0) {
|
"Messages before the new logger might not be available.");
|
||||||
ReportingLevel = _EGL_INFO;
|
}
|
||||||
}
|
|
||||||
else if (strcasecmp(log_env, "debug") == 0) {
|
|
||||||
ReportingLevel = _EGL_DEBUG;
|
/**
|
||||||
}
|
* Set the log reporting level.
|
||||||
else {
|
*/
|
||||||
fprintf(stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. "
|
void
|
||||||
"Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
|
_eglSetLogLevel(EGLint level)
|
||||||
"Got \"%s\". Falling back to \"%s\".\n",
|
{
|
||||||
log_env, FALLBACK_LOG_LEVEL_STR);
|
switch (level) {
|
||||||
ReportingLevel = FALLBACK_LOG_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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log a message to stderr.
|
* 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 {
|
||||||
|
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\".",
|
||||||
|
log_env, level_strings[FALLBACK_LOG_LEVEL]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a message with message logger.
|
||||||
* \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
|
* \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@@ -57,40 +150,26 @@ _eglLog(EGLint level, const char *fmtStr, ...)
|
|||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
char msg[MAXSTRING];
|
char msg[MAXSTRING];
|
||||||
const char *levelStr;
|
|
||||||
static int log_level_initialized = 0;
|
|
||||||
|
|
||||||
if (!log_level_initialized) {
|
/* one-time initialization; a little race here is fine */
|
||||||
log_level_initialize();
|
if (!logging.initialized)
|
||||||
log_level_initialized = 1;
|
_eglInitLogger();
|
||||||
}
|
if (level > logging.level || level < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (level <= ReportingLevel) {
|
_eglLockMutex(&logging.mutex);
|
||||||
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 = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (logging.logger) {
|
||||||
va_start(args, fmtStr);
|
va_start(args, fmtStr);
|
||||||
vsnprintf(msg, MAXSTRING, fmtStr, args);
|
vsnprintf(msg, MAXSTRING, fmtStr, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
fprintf(stderr, "libEGL %s: %s\n", levelStr, msg);
|
logging.logger(level, msg);
|
||||||
|
logging.num_messages++;
|
||||||
if (level == _EGL_FATAL) {
|
|
||||||
exit(1); /* or abort()? */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_eglUnlockMutex(&logging.mutex);
|
||||||
|
|
||||||
|
if (level == _EGL_FATAL)
|
||||||
|
exit(1); /* or abort()? */
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,17 @@
|
|||||||
#define _EGL_DEBUG 3 /* useful info for debugging */
|
#define _EGL_DEBUG 3 /* useful info for debugging */
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*_EGLLogProc)(EGLint level, const char *msg);
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_eglSetLogProc(_EGLLogProc logger);
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_eglSetLogLevel(EGLint level);
|
||||||
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
_eglLog(EGLint level, const char *fmtStr, ...);
|
_eglLog(EGLint level, const char *fmtStr, ...);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user