+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright 2010 LunarG, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
/**
* Logging facility for debug/info messages.
* _EGL_FATAL messages are printed to stderr
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
+#include "c11/threads.h"
+#include "util/macros.h"
+#include "util/u_string.h"
+
#include "egllog.h"
+#ifdef HAVE_ANDROID_PLATFORM
+#define LOG_TAG "EGL-MAIN"
+#if ANDROID_API_LEVEL >= 26
+#include <log/log.h>
+#else
+#include <cutils/log.h>
+#endif /* use log/log.h start from android 8 major version */
+
+#endif /* HAVE_ANDROID_PLATFORM */
+
#define MAXSTRING 1000
-#define FALLBACK_LOG_LEVEL _EGL_WARNING
-#define FALLBACK_LOG_LEVEL_STR "warning"
+#define FALLBACK_LOG_LEVEL _EGL_WARNING
+
+
+static struct {
+ mtx_t mutex;
-static EGLint ReportingLevel = -1;
+ EGLBoolean initialized;
+ EGLint level;
+} logging = {
+ .mutex = _MTX_INITIALIZER_NP,
+ .initialized = EGL_FALSE,
+ .level = FALLBACK_LOG_LEVEL,
+};
+static const char *level_strings[] = {
+ [_EGL_FATAL] = "fatal",
+ [_EGL_WARNING] = "warning",
+ [_EGL_INFO] = "info",
+ [_EGL_DEBUG] = "debug",
+};
+
+/**
+ * The default logger. It prints the message to stderr.
+ */
static void
-log_level_initialize(void)
+_eglDefaultLogger(EGLint level, const char *msg)
{
-#if defined(_EGL_PLATFORM_X)
- char *log_env = getenv("EGL_LOG_LEVEL");
+#ifdef HAVE_ANDROID_PLATFORM
+ static const int egl2alog[] = {
+ [_EGL_FATAL] = ANDROID_LOG_ERROR,
+ [_EGL_WARNING] = ANDROID_LOG_WARN,
+ [_EGL_INFO] = ANDROID_LOG_INFO,
+ [_EGL_DEBUG] = ANDROID_LOG_DEBUG,
+ };
+ LOG_PRI(egl2alog[level], LOG_TAG, "%s", msg);
#else
- char *log_env = NULL;
-#endif
+ fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg);
+#endif /* HAVE_ANDROID_PLATFORM */
+}
- 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;
- }
- else if (strcasecmp(log_env, "info") == 0) {
- ReportingLevel = _EGL_INFO;
- }
- else if (strcasecmp(log_env, "debug") == 0) {
- ReportingLevel = _EGL_DEBUG;
+
+/**
+ * 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; i < ARRAY_SIZE(level_strings); i++) {
+ if (strcasecmp(log_env, level_strings[i]) == 0) {
+ level = i;
+ break;
+ }
+ }
}
- else {
- fprintf(stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. "
+
+ 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
{
va_list args;
char msg[MAXSTRING];
- const char *levelStr;
- static int log_level_initialized = 0;
+ int ret;
- 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 = "";
- }
+ mtx_lock(&logging.mutex);
- va_start(args, fmtStr);
- vsnprintf(msg, MAXSTRING, fmtStr, args);
- va_end(args);
+ va_start(args, fmtStr);
+ ret = vsnprintf(msg, MAXSTRING, fmtStr, args);
+ if (ret < 0 || ret >= MAXSTRING)
+ strcpy(msg, "<message truncated>");
+ va_end(args);
- fprintf(stderr, "libEGL %s: %s\n", levelStr, msg);
+ _eglDefaultLogger(level, msg);
- if (level == _EGL_FATAL) {
- exit(1); /* or abort()? */
- }
- }
+ mtx_unlock(&logging.mutex);
+
+ if (level == _EGL_FATAL)
+ exit(1); /* or abort()? */
}