1f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu/**************************************************************************
2f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
3f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * Copyright 2010 LunarG, Inc.
6f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * All Rights Reserved.
7f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
8f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * Permission is hereby granted, free of charge, to any person obtaining a
9f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * copy of this software and associated documentation files (the
10f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * "Software"), to deal in the Software without restriction, including
11f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * without limitation the rights to use, copy, modify, merge, publish,
12f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * distribute, sub license, and/or sell copies of the Software, and to
13f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * permit persons to whom the Software is furnished to do so, subject to
14f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * the following conditions:
15f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
16f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * The above copyright notice and this permission notice (including the
17f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * next paragraph) shall be included in all copies or substantial portions
18f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * of the Software.
19f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
20f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu * DEALINGS IN THE SOFTWARE.
27f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu *
28f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu **************************************************************************/
29f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu
30f2001df508fda599a18b3586d2775e970a3db13aChia-I Wu
31f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul/**
32f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul * Logging facility for debug/info messages.
33f6e030f531f7292a373a7cd633e8af9f97726266Brian Paul * _EGL_FATAL messages are printed to stderr
34f6e030f531f7292a373a7cd633e8af9f97726266Brian Paul * The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs.
35f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul */
36f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
37f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
38f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul#include <stdarg.h>
39f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul#include <stdio.h>
40f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul#include <stdlib.h>
41f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
42f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul#include "egllog.h"
431e6c10f4be9e36cc052a6b47fb2cb1eae60caa00Chia-I Wu#include "eglstring.h"
44f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu#include "eglmutex.h"
45f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
46f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul#define MAXSTRING 1000
47f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu#define FALLBACK_LOG_LEVEL _EGL_WARNING
48f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
49f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
50f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wustatic struct {
51f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   _EGLMutex mutex;
5220e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair
53f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   EGLBoolean initialized;
54f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   EGLint level;
55f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   _EGLLogProc logger;
56f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   EGLint num_messages;
57f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu} logging = {
58f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   _EGL_MUTEX_INITIALIZER,
59f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   EGL_FALSE,
60f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   FALLBACK_LOG_LEVEL,
61f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   NULL,
62f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   0
63f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu};
64f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
65f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wustatic const char *level_strings[] = {
66f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   /* the order is important */
67f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   "fatal",
68f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   "warning",
69f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   "info",
70f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   "debug",
71f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   NULL
72f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu};
73f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
74f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
75f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu/**
76f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu * Set the function to be called when there is a message to log.
77f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu * Note that the function will be called with an internal lock held.
78f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu * Recursive logging is not allowed.
79f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu */
80f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wuvoid
81f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu_eglSetLogProc(_EGLLogProc logger)
8220e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair{
83f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   EGLint num_messages = 0;
8420e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair
85f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   _eglLockMutex(&logging.mutex);
86f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
87f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (logging.logger != logger) {
88f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      logging.logger = logger;
89f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
90f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      num_messages = logging.num_messages;
91f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      logging.num_messages = 0;
9220e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair   }
93f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
94f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   _eglUnlockMutex(&logging.mutex);
95f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
96f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (num_messages)
97f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      _eglLog(_EGL_DEBUG,
98f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu              "New logger installed. "
99f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu              "Messages before the new logger might not be available.");
100f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu}
101f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
102f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
103f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu/**
104f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu * Set the log reporting level.
105f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu */
106f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wuvoid
107f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu_eglSetLogLevel(EGLint level)
108f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu{
109f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   switch (level) {
110f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   case _EGL_FATAL:
111f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   case _EGL_WARNING:
112f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   case _EGL_INFO:
113f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   case _EGL_DEBUG:
114f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      _eglLockMutex(&logging.mutex);
115f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      logging.level = level;
116f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      _eglUnlockMutex(&logging.mutex);
117f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      break;
118f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   default:
119f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      break;
12020e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair   }
121f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu}
122f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
123f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
124f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu/**
125f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu * The default logger.  It prints the message to stderr.
126f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu */
127f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wustatic void
128f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu_eglDefaultLogger(EGLint level, const char *msg)
129f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu{
130f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg);
131f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu}
132f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
133f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
134f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu/**
135f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu * Initialize the logging facility.
136f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu */
137f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wustatic void
138f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu_eglInitLogger(void)
139f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu{
140f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   const char *log_env;
141f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   EGLint i, level = -1;
142f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
143f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (logging.initialized)
144f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      return;
145f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
146f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   log_env = getenv("EGL_LOG_LEVEL");
147f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (log_env) {
148f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      for (i = 0; level_strings[i]; i++) {
1491e6c10f4be9e36cc052a6b47fb2cb1eae60caa00Chia-I Wu         if (_eglstrcasecmp(log_env, level_strings[i]) == 0) {
150f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu            level = i;
151f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu            break;
152f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu         }
153f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      }
15420e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair   }
15520e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair   else {
156f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      level = FALLBACK_LOG_LEVEL;
157f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   }
158f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
159f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   logging.logger = _eglDefaultLogger;
160f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL;
161f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   logging.initialized = EGL_TRUE;
162f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
163f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   /* it is fine to call _eglLog now */
164f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (log_env && level < 0) {
165f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      _eglLog(_EGL_WARNING,
166f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu              "Unrecognized EGL_LOG_LEVEL environment variable value. "
167f6e030f531f7292a373a7cd633e8af9f97726266Brian Paul              "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
168f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu              "Got \"%s\". Falling back to \"%s\".",
169f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu              log_env, level_strings[FALLBACK_LOG_LEVEL]);
17020e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair   }
17120e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair}
172f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
173f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
174f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul/**
175f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu * Log a message with message logger.
176f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul * \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
177f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul */
178f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paulvoid
179f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul_eglLog(EGLint level, const char *fmtStr, ...)
180f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul{
181f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul   va_list args;
182f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul   char msg[MAXSTRING];
183ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu   int ret;
18420e851bb9a6737194bc0effcb155b2fdb23acaaaChristian Neumair
185f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   /* one-time initialization; a little race here is fine */
186f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (!logging.initialized)
187f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      _eglInitLogger();
188f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (level > logging.level || level < 0)
189f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      return;
190f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
191f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   _eglLockMutex(&logging.mutex);
192f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
193f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (logging.logger) {
194f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul      va_start(args, fmtStr);
195ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      ret = vsnprintf(msg, MAXSTRING, fmtStr, args);
196ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu      if (ret < 0 || ret >= MAXSTRING)
197ad00a92ee720c275d3852faea4e442a8da876ca2Chia-I Wu         strcpy(msg, "<message truncated>");
198f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul      va_end(args);
199f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul
200f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      logging.logger(level, msg);
201f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      logging.num_messages++;
202f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul   }
203f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
204f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   _eglUnlockMutex(&logging.mutex);
205f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu
206f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu   if (level == _EGL_FATAL)
207f1c5cab5525dfcb8edffa275e7c8c3e753c7536fChia-I Wu      exit(1); /* or abort()? */
208f049ca4e33e0e5d06223a1c05815bc564b4bf06eBrian Paul}
209