egllog.c revision af69d88d
13464ebd5Sriastradh/**************************************************************************
23464ebd5Sriastradh *
3af69d88dSmrg * Copyright 2008 VMware, Inc.
43464ebd5Sriastradh * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
53464ebd5Sriastradh * Copyright 2010 LunarG, Inc.
63464ebd5Sriastradh * All Rights Reserved.
73464ebd5Sriastradh *
83464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
93464ebd5Sriastradh * copy of this software and associated documentation files (the
103464ebd5Sriastradh * "Software"), to deal in the Software without restriction, including
113464ebd5Sriastradh * without limitation the rights to use, copy, modify, merge, publish,
123464ebd5Sriastradh * distribute, sub license, and/or sell copies of the Software, and to
133464ebd5Sriastradh * permit persons to whom the Software is furnished to do so, subject to
143464ebd5Sriastradh * the following conditions:
153464ebd5Sriastradh *
163464ebd5Sriastradh * The above copyright notice and this permission notice (including the
173464ebd5Sriastradh * next paragraph) shall be included in all copies or substantial portions
183464ebd5Sriastradh * of the Software.
193464ebd5Sriastradh *
203464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
213464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
223464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
233464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
243464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
253464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
263464ebd5Sriastradh * DEALINGS IN THE SOFTWARE.
273464ebd5Sriastradh *
283464ebd5Sriastradh **************************************************************************/
293464ebd5Sriastradh
303464ebd5Sriastradh
314a49301eSmrg/**
324a49301eSmrg * Logging facility for debug/info messages.
334a49301eSmrg * _EGL_FATAL messages are printed to stderr
344a49301eSmrg * The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs.
354a49301eSmrg */
364a49301eSmrg
374a49301eSmrg
384a49301eSmrg#include <stdarg.h>
394a49301eSmrg#include <stdio.h>
404a49301eSmrg#include <stdlib.h>
414a49301eSmrg
424a49301eSmrg#include "egllog.h"
433464ebd5Sriastradh#include "eglstring.h"
444a49301eSmrg#include "eglmutex.h"
454a49301eSmrg
464a49301eSmrg#define MAXSTRING 1000
474a49301eSmrg#define FALLBACK_LOG_LEVEL _EGL_WARNING
484a49301eSmrg
494a49301eSmrg
504a49301eSmrgstatic struct {
514a49301eSmrg   _EGLMutex mutex;
524a49301eSmrg
534a49301eSmrg   EGLBoolean initialized;
544a49301eSmrg   EGLint level;
554a49301eSmrg   _EGLLogProc logger;
564a49301eSmrg   EGLint num_messages;
574a49301eSmrg} logging = {
584a49301eSmrg   _EGL_MUTEX_INITIALIZER,
594a49301eSmrg   EGL_FALSE,
604a49301eSmrg   FALLBACK_LOG_LEVEL,
614a49301eSmrg   NULL,
624a49301eSmrg   0
634a49301eSmrg};
644a49301eSmrg
654a49301eSmrgstatic const char *level_strings[] = {
664a49301eSmrg   /* the order is important */
674a49301eSmrg   "fatal",
684a49301eSmrg   "warning",
694a49301eSmrg   "info",
704a49301eSmrg   "debug",
714a49301eSmrg   NULL
724a49301eSmrg};
734a49301eSmrg
744a49301eSmrg
754a49301eSmrg/**
764a49301eSmrg * Set the function to be called when there is a message to log.
774a49301eSmrg * Note that the function will be called with an internal lock held.
784a49301eSmrg * Recursive logging is not allowed.
794a49301eSmrg */
804a49301eSmrgvoid
814a49301eSmrg_eglSetLogProc(_EGLLogProc logger)
824a49301eSmrg{
834a49301eSmrg   EGLint num_messages = 0;
844a49301eSmrg
854a49301eSmrg   _eglLockMutex(&logging.mutex);
864a49301eSmrg
874a49301eSmrg   if (logging.logger != logger) {
884a49301eSmrg      logging.logger = logger;
894a49301eSmrg
904a49301eSmrg      num_messages = logging.num_messages;
914a49301eSmrg      logging.num_messages = 0;
924a49301eSmrg   }
934a49301eSmrg
944a49301eSmrg   _eglUnlockMutex(&logging.mutex);
954a49301eSmrg
964a49301eSmrg   if (num_messages)
974a49301eSmrg      _eglLog(_EGL_DEBUG,
984a49301eSmrg              "New logger installed. "
994a49301eSmrg              "Messages before the new logger might not be available.");
1004a49301eSmrg}
1014a49301eSmrg
1024a49301eSmrg
1034a49301eSmrg/**
1044a49301eSmrg * Set the log reporting level.
1054a49301eSmrg */
1064a49301eSmrgvoid
1074a49301eSmrg_eglSetLogLevel(EGLint level)
1084a49301eSmrg{
1094a49301eSmrg   switch (level) {
1104a49301eSmrg   case _EGL_FATAL:
1114a49301eSmrg   case _EGL_WARNING:
1124a49301eSmrg   case _EGL_INFO:
1134a49301eSmrg   case _EGL_DEBUG:
1144a49301eSmrg      _eglLockMutex(&logging.mutex);
1154a49301eSmrg      logging.level = level;
1164a49301eSmrg      _eglUnlockMutex(&logging.mutex);
1174a49301eSmrg      break;
1184a49301eSmrg   default:
1194a49301eSmrg      break;
1204a49301eSmrg   }
1214a49301eSmrg}
1224a49301eSmrg
1234a49301eSmrg
1244a49301eSmrg/**
1254a49301eSmrg * The default logger.  It prints the message to stderr.
1264a49301eSmrg */
1274a49301eSmrgstatic void
1284a49301eSmrg_eglDefaultLogger(EGLint level, const char *msg)
1294a49301eSmrg{
1304a49301eSmrg   fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg);
1314a49301eSmrg}
1324a49301eSmrg
1334a49301eSmrg
1344a49301eSmrg/**
1354a49301eSmrg * Initialize the logging facility.
1364a49301eSmrg */
1374a49301eSmrgstatic void
1384a49301eSmrg_eglInitLogger(void)
1394a49301eSmrg{
1404a49301eSmrg   const char *log_env;
1414a49301eSmrg   EGLint i, level = -1;
1424a49301eSmrg
1434a49301eSmrg   if (logging.initialized)
1444a49301eSmrg      return;
1454a49301eSmrg
1464a49301eSmrg   log_env = getenv("EGL_LOG_LEVEL");
1474a49301eSmrg   if (log_env) {
1484a49301eSmrg      for (i = 0; level_strings[i]; i++) {
1493464ebd5Sriastradh         if (_eglstrcasecmp(log_env, level_strings[i]) == 0) {
1504a49301eSmrg            level = i;
1514a49301eSmrg            break;
1524a49301eSmrg         }
1534a49301eSmrg      }
1544a49301eSmrg   }
1554a49301eSmrg   else {
1564a49301eSmrg      level = FALLBACK_LOG_LEVEL;
1574a49301eSmrg   }
1584a49301eSmrg
1594a49301eSmrg   logging.logger = _eglDefaultLogger;
1604a49301eSmrg   logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL;
1614a49301eSmrg   logging.initialized = EGL_TRUE;
1624a49301eSmrg
1634a49301eSmrg   /* it is fine to call _eglLog now */
1644a49301eSmrg   if (log_env && level < 0) {
1654a49301eSmrg      _eglLog(_EGL_WARNING,
1664a49301eSmrg              "Unrecognized EGL_LOG_LEVEL environment variable value. "
1674a49301eSmrg              "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
1684a49301eSmrg              "Got \"%s\". Falling back to \"%s\".",
1694a49301eSmrg              log_env, level_strings[FALLBACK_LOG_LEVEL]);
1704a49301eSmrg   }
1714a49301eSmrg}
1724a49301eSmrg
1734a49301eSmrg
1744a49301eSmrg/**
1754a49301eSmrg * Log a message with message logger.
1764a49301eSmrg * \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
1774a49301eSmrg */
1784a49301eSmrgvoid
1794a49301eSmrg_eglLog(EGLint level, const char *fmtStr, ...)
1804a49301eSmrg{
1814a49301eSmrg   va_list args;
1824a49301eSmrg   char msg[MAXSTRING];
1833464ebd5Sriastradh   int ret;
1844a49301eSmrg
1854a49301eSmrg   /* one-time initialization; a little race here is fine */
1864a49301eSmrg   if (!logging.initialized)
1874a49301eSmrg      _eglInitLogger();
1884a49301eSmrg   if (level > logging.level || level < 0)
1894a49301eSmrg      return;
1904a49301eSmrg
1914a49301eSmrg   _eglLockMutex(&logging.mutex);
1924a49301eSmrg
1934a49301eSmrg   if (logging.logger) {
1944a49301eSmrg      va_start(args, fmtStr);
1953464ebd5Sriastradh      ret = vsnprintf(msg, MAXSTRING, fmtStr, args);
1963464ebd5Sriastradh      if (ret < 0 || ret >= MAXSTRING)
1973464ebd5Sriastradh         strcpy(msg, "<message truncated>");
1984a49301eSmrg      va_end(args);
1994a49301eSmrg
2004a49301eSmrg      logging.logger(level, msg);
2014a49301eSmrg      logging.num_messages++;
2024a49301eSmrg   }
2034a49301eSmrg
2044a49301eSmrg   _eglUnlockMutex(&logging.mutex);
2054a49301eSmrg
2064a49301eSmrg   if (level == _EGL_FATAL)
2074a49301eSmrg      exit(1); /* or abort()? */
2084a49301eSmrg}
209