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