egllog.c revision 4a49301e
14a49301eSmrg/** 24a49301eSmrg * Logging facility for debug/info messages. 34a49301eSmrg * _EGL_FATAL messages are printed to stderr 44a49301eSmrg * The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs. 54a49301eSmrg */ 64a49301eSmrg 74a49301eSmrg 84a49301eSmrg#include <stdarg.h> 94a49301eSmrg#include <stdio.h> 104a49301eSmrg#include <stdlib.h> 114a49301eSmrg#include <string.h> 124a49301eSmrg 134a49301eSmrg#include "egllog.h" 144a49301eSmrg#include "eglmutex.h" 154a49301eSmrg 164a49301eSmrg#define MAXSTRING 1000 174a49301eSmrg#define FALLBACK_LOG_LEVEL _EGL_WARNING 184a49301eSmrg 194a49301eSmrg 204a49301eSmrgstatic struct { 214a49301eSmrg _EGLMutex mutex; 224a49301eSmrg 234a49301eSmrg EGLBoolean initialized; 244a49301eSmrg EGLint level; 254a49301eSmrg _EGLLogProc logger; 264a49301eSmrg EGLint num_messages; 274a49301eSmrg} logging = { 284a49301eSmrg _EGL_MUTEX_INITIALIZER, 294a49301eSmrg EGL_FALSE, 304a49301eSmrg FALLBACK_LOG_LEVEL, 314a49301eSmrg NULL, 324a49301eSmrg 0 334a49301eSmrg}; 344a49301eSmrg 354a49301eSmrgstatic const char *level_strings[] = { 364a49301eSmrg /* the order is important */ 374a49301eSmrg "fatal", 384a49301eSmrg "warning", 394a49301eSmrg "info", 404a49301eSmrg "debug", 414a49301eSmrg NULL 424a49301eSmrg}; 434a49301eSmrg 444a49301eSmrg 454a49301eSmrg/** 464a49301eSmrg * Set the function to be called when there is a message to log. 474a49301eSmrg * Note that the function will be called with an internal lock held. 484a49301eSmrg * Recursive logging is not allowed. 494a49301eSmrg */ 504a49301eSmrgvoid 514a49301eSmrg_eglSetLogProc(_EGLLogProc logger) 524a49301eSmrg{ 534a49301eSmrg EGLint num_messages = 0; 544a49301eSmrg 554a49301eSmrg _eglLockMutex(&logging.mutex); 564a49301eSmrg 574a49301eSmrg if (logging.logger != logger) { 584a49301eSmrg logging.logger = logger; 594a49301eSmrg 604a49301eSmrg num_messages = logging.num_messages; 614a49301eSmrg logging.num_messages = 0; 624a49301eSmrg } 634a49301eSmrg 644a49301eSmrg _eglUnlockMutex(&logging.mutex); 654a49301eSmrg 664a49301eSmrg if (num_messages) 674a49301eSmrg _eglLog(_EGL_DEBUG, 684a49301eSmrg "New logger installed. " 694a49301eSmrg "Messages before the new logger might not be available."); 704a49301eSmrg} 714a49301eSmrg 724a49301eSmrg 734a49301eSmrg/** 744a49301eSmrg * Set the log reporting level. 754a49301eSmrg */ 764a49301eSmrgvoid 774a49301eSmrg_eglSetLogLevel(EGLint level) 784a49301eSmrg{ 794a49301eSmrg switch (level) { 804a49301eSmrg case _EGL_FATAL: 814a49301eSmrg case _EGL_WARNING: 824a49301eSmrg case _EGL_INFO: 834a49301eSmrg case _EGL_DEBUG: 844a49301eSmrg _eglLockMutex(&logging.mutex); 854a49301eSmrg logging.level = level; 864a49301eSmrg _eglUnlockMutex(&logging.mutex); 874a49301eSmrg break; 884a49301eSmrg default: 894a49301eSmrg break; 904a49301eSmrg } 914a49301eSmrg} 924a49301eSmrg 934a49301eSmrg 944a49301eSmrg/** 954a49301eSmrg * The default logger. It prints the message to stderr. 964a49301eSmrg */ 974a49301eSmrgstatic void 984a49301eSmrg_eglDefaultLogger(EGLint level, const char *msg) 994a49301eSmrg{ 1004a49301eSmrg fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg); 1014a49301eSmrg} 1024a49301eSmrg 1034a49301eSmrg 1044a49301eSmrg/** 1054a49301eSmrg * Initialize the logging facility. 1064a49301eSmrg */ 1074a49301eSmrgstatic void 1084a49301eSmrg_eglInitLogger(void) 1094a49301eSmrg{ 1104a49301eSmrg const char *log_env; 1114a49301eSmrg EGLint i, level = -1; 1124a49301eSmrg 1134a49301eSmrg if (logging.initialized) 1144a49301eSmrg return; 1154a49301eSmrg 1164a49301eSmrg log_env = getenv("EGL_LOG_LEVEL"); 1174a49301eSmrg if (log_env) { 1184a49301eSmrg for (i = 0; level_strings[i]; i++) { 1194a49301eSmrg if (strcasecmp(log_env, level_strings[i]) == 0) { 1204a49301eSmrg level = i; 1214a49301eSmrg break; 1224a49301eSmrg } 1234a49301eSmrg } 1244a49301eSmrg } 1254a49301eSmrg else { 1264a49301eSmrg level = FALLBACK_LOG_LEVEL; 1274a49301eSmrg } 1284a49301eSmrg 1294a49301eSmrg logging.logger = _eglDefaultLogger; 1304a49301eSmrg logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL; 1314a49301eSmrg logging.initialized = EGL_TRUE; 1324a49301eSmrg 1334a49301eSmrg /* it is fine to call _eglLog now */ 1344a49301eSmrg if (log_env && level < 0) { 1354a49301eSmrg _eglLog(_EGL_WARNING, 1364a49301eSmrg "Unrecognized EGL_LOG_LEVEL environment variable value. " 1374a49301eSmrg "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". " 1384a49301eSmrg "Got \"%s\". Falling back to \"%s\".", 1394a49301eSmrg log_env, level_strings[FALLBACK_LOG_LEVEL]); 1404a49301eSmrg } 1414a49301eSmrg} 1424a49301eSmrg 1434a49301eSmrg 1444a49301eSmrg/** 1454a49301eSmrg * Log a message with message logger. 1464a49301eSmrg * \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG. 1474a49301eSmrg */ 1484a49301eSmrgvoid 1494a49301eSmrg_eglLog(EGLint level, const char *fmtStr, ...) 1504a49301eSmrg{ 1514a49301eSmrg va_list args; 1524a49301eSmrg char msg[MAXSTRING]; 1534a49301eSmrg 1544a49301eSmrg /* one-time initialization; a little race here is fine */ 1554a49301eSmrg if (!logging.initialized) 1564a49301eSmrg _eglInitLogger(); 1574a49301eSmrg if (level > logging.level || level < 0) 1584a49301eSmrg return; 1594a49301eSmrg 1604a49301eSmrg _eglLockMutex(&logging.mutex); 1614a49301eSmrg 1624a49301eSmrg if (logging.logger) { 1634a49301eSmrg va_start(args, fmtStr); 1644a49301eSmrg vsnprintf(msg, MAXSTRING, fmtStr, args); 1654a49301eSmrg va_end(args); 1664a49301eSmrg 1674a49301eSmrg logging.logger(level, msg); 1684a49301eSmrg logging.num_messages++; 1694a49301eSmrg } 1704a49301eSmrg 1714a49301eSmrg _eglUnlockMutex(&logging.mutex); 1724a49301eSmrg 1734a49301eSmrg if (level == _EGL_FATAL) 1744a49301eSmrg exit(1); /* or abort()? */ 1754a49301eSmrg} 176