1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 5 * Copyright 2010 LunarG, Inc. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30 31/** 32 * Logging facility for debug/info messages. 33 * _EGL_FATAL messages are printed to stderr 34 * The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs. 35 */ 36 37 38#include <stdarg.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include "c11/threads.h" 43#include "util/macros.h" 44#include "util/u_string.h" 45 46#include "egllog.h" 47 48#ifdef HAVE_ANDROID_PLATFORM 49#define LOG_TAG "EGL-MAIN" 50#if ANDROID_API_LEVEL >= 26 51#include <log/log.h> 52#else 53#include <cutils/log.h> 54#endif /* use log/log.h start from android 8 major version */ 55 56#endif /* HAVE_ANDROID_PLATFORM */ 57 58#define MAXSTRING 1000 59#define FALLBACK_LOG_LEVEL _EGL_WARNING 60 61 62static struct { 63 mtx_t mutex; 64 65 EGLBoolean initialized; 66 EGLint level; 67} logging = { 68 .mutex = _MTX_INITIALIZER_NP, 69 .initialized = EGL_FALSE, 70 .level = FALLBACK_LOG_LEVEL, 71}; 72 73static const char *level_strings[] = { 74 [_EGL_FATAL] = "fatal", 75 [_EGL_WARNING] = "warning", 76 [_EGL_INFO] = "info", 77 [_EGL_DEBUG] = "debug", 78}; 79 80 81/** 82 * The default logger. It prints the message to stderr. 83 */ 84static void 85_eglDefaultLogger(EGLint level, const char *msg) 86{ 87#ifdef HAVE_ANDROID_PLATFORM 88 static const int egl2alog[] = { 89 [_EGL_FATAL] = ANDROID_LOG_ERROR, 90 [_EGL_WARNING] = ANDROID_LOG_WARN, 91 [_EGL_INFO] = ANDROID_LOG_INFO, 92 [_EGL_DEBUG] = ANDROID_LOG_DEBUG, 93 }; 94 LOG_PRI(egl2alog[level], LOG_TAG, "%s", msg); 95#else 96 fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg); 97#endif /* HAVE_ANDROID_PLATFORM */ 98} 99 100 101/** 102 * Initialize the logging facility. 103 */ 104static void 105_eglInitLogger(void) 106{ 107 const char *log_env; 108 EGLint i, level = -1; 109 110 if (logging.initialized) 111 return; 112 113 log_env = getenv("EGL_LOG_LEVEL"); 114 if (log_env) { 115 for (i = 0; i < ARRAY_SIZE(level_strings); i++) { 116 if (strcasecmp(log_env, level_strings[i]) == 0) { 117 level = i; 118 break; 119 } 120 } 121 } 122 123 logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL; 124 logging.initialized = EGL_TRUE; 125 126 /* it is fine to call _eglLog now */ 127 if (log_env && level < 0) { 128 _eglLog(_EGL_WARNING, 129 "Unrecognized EGL_LOG_LEVEL environment variable value. " 130 "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". " 131 "Got \"%s\". Falling back to \"%s\".", 132 log_env, level_strings[FALLBACK_LOG_LEVEL]); 133 } 134} 135 136/** 137 * Return the log level. 138 */ 139EGLint 140_eglGetLogLevel(void) 141{ 142 return logging.level; 143} 144 145 146/** 147 * Log a message with message logger. 148 * \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG. 149 */ 150void 151_eglLog(EGLint level, const char *fmtStr, ...) 152{ 153 va_list args; 154 char msg[MAXSTRING]; 155 int ret; 156 157 /* one-time initialization; a little race here is fine */ 158 if (!logging.initialized) 159 _eglInitLogger(); 160 if (level > logging.level || level < 0) 161 return; 162 163 mtx_lock(&logging.mutex); 164 165 va_start(args, fmtStr); 166 ret = vsnprintf(msg, MAXSTRING, fmtStr, args); 167 if (ret < 0 || ret >= MAXSTRING) 168 strcpy(msg, "<message truncated>"); 169 va_end(args); 170 171 _eglDefaultLogger(level, msg); 172 173 mtx_unlock(&logging.mutex); 174 175 if (level == _EGL_FATAL) 176 exit(1); /* or abort()? */ 177} 178