xref: /third_party/mesa3d/src/egl/main/eglcurrent.c (revision bf215546)
1/**************************************************************************
2 *
3 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdarg.h>
33#include "c11/threads.h"
34#include "util/u_thread.h"
35#include "util/u_string.h"
36
37#include "egllog.h"
38#include "eglcurrent.h"
39#include "eglglobals.h"
40
41static __THREAD_INITIAL_EXEC _EGLThreadInfo _egl_TLS = {
42   .inited = false
43};
44
45static void
46_eglInitThreadInfo(_EGLThreadInfo *t)
47{
48   t->LastError = EGL_SUCCESS;
49   /* default, per EGL spec */
50   t->CurrentAPI = EGL_OPENGL_ES_API;
51}
52
53
54/**
55 * Return the calling thread's thread info.
56 * If the calling thread nevers calls this function before, or if its thread
57 * info was destroyed, reinitialize it.  This function never returns NULL.
58 */
59_EGLThreadInfo *
60_eglGetCurrentThread(void)
61{
62   _EGLThreadInfo *current = &_egl_TLS;
63   if (unlikely(!current->inited)) {
64      memset(current, 0, sizeof(current[0]));
65      _eglInitThreadInfo(current);
66      current->inited = true;
67   }
68   return current;
69}
70
71
72/**
73 * Destroy the calling thread's thread info.
74 */
75void
76_eglDestroyCurrentThread(void)
77{
78   _EGLThreadInfo *t = _eglGetCurrentThread();
79   t->inited = false;
80}
81
82
83/**
84 * Return the currently bound context of the current API, or NULL.
85 */
86_EGLContext *
87_eglGetCurrentContext(void)
88{
89   _EGLThreadInfo *t = _eglGetCurrentThread();
90   return t->CurrentContext;
91}
92
93
94/**
95 * Record EGL error code and return EGL_FALSE.
96 */
97static EGLBoolean
98_eglInternalError(EGLint errCode, const char *msg)
99{
100   _EGLThreadInfo *t = _eglGetCurrentThread();
101
102   t->LastError = errCode;
103
104   if (errCode != EGL_SUCCESS) {
105      const char *s;
106
107      switch (errCode) {
108      case EGL_BAD_ACCESS:
109         s = "EGL_BAD_ACCESS";
110         break;
111      case EGL_BAD_ALLOC:
112         s = "EGL_BAD_ALLOC";
113         break;
114      case EGL_BAD_ATTRIBUTE:
115         s = "EGL_BAD_ATTRIBUTE";
116         break;
117      case EGL_BAD_CONFIG:
118         s = "EGL_BAD_CONFIG";
119         break;
120      case EGL_BAD_CONTEXT:
121         s = "EGL_BAD_CONTEXT";
122         break;
123      case EGL_BAD_CURRENT_SURFACE:
124         s = "EGL_BAD_CURRENT_SURFACE";
125         break;
126      case EGL_BAD_DISPLAY:
127         s = "EGL_BAD_DISPLAY";
128         break;
129      case EGL_BAD_MATCH:
130         s = "EGL_BAD_MATCH";
131         break;
132      case EGL_BAD_NATIVE_PIXMAP:
133         s = "EGL_BAD_NATIVE_PIXMAP";
134         break;
135      case EGL_BAD_NATIVE_WINDOW:
136         s = "EGL_BAD_NATIVE_WINDOW";
137         break;
138      case EGL_BAD_PARAMETER:
139         s = "EGL_BAD_PARAMETER";
140         break;
141      case EGL_BAD_SURFACE:
142         s = "EGL_BAD_SURFACE";
143         break;
144      case EGL_NOT_INITIALIZED:
145         s = "EGL_NOT_INITIALIZED";
146         break;
147      default:
148         s = "other EGL error";
149      }
150      _eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
151   }
152
153   return EGL_FALSE;
154}
155
156EGLBoolean
157_eglError(EGLint errCode, const char *msg)
158{
159   if (errCode != EGL_SUCCESS) {
160      EGLint type;
161      if (errCode == EGL_BAD_ALLOC)
162         type = EGL_DEBUG_MSG_CRITICAL_KHR;
163      else
164         type = EGL_DEBUG_MSG_ERROR_KHR;
165
166      _eglDebugReport(errCode, NULL, type, msg);
167   } else
168      _eglInternalError(errCode, msg);
169
170   return EGL_FALSE;
171}
172
173void
174_eglDebugReport(EGLenum error, const char *funcName,
175      EGLint type, const char *message, ...)
176{
177   _EGLThreadInfo *thr = _eglGetCurrentThread();
178   EGLDEBUGPROCKHR callback = NULL;
179   va_list args;
180
181   if (funcName == NULL)
182      funcName = thr->CurrentFuncName;
183
184   mtx_lock(_eglGlobal.Mutex);
185   if (_eglGlobal.debugTypesEnabled & DebugBitFromType(type))
186      callback = _eglGlobal.debugCallback;
187
188   mtx_unlock(_eglGlobal.Mutex);
189
190   char *message_buf = NULL;
191   if (message != NULL) {
192      va_start(args, message);
193      if (vasprintf(&message_buf, message, args) < 0)
194         message_buf = NULL;
195      va_end(args);
196   }
197
198   if (callback != NULL) {
199      callback(error, funcName, type, thr->Label, thr->CurrentObjectLabel,
200               message_buf);
201   }
202
203   if (type == EGL_DEBUG_MSG_CRITICAL_KHR || type == EGL_DEBUG_MSG_ERROR_KHR) {
204      char *func_message_buf = NULL;
205      /* Note: _eglError() is often called with msg == thr->currentFuncName */
206      if (message_buf && funcName && strcmp(message_buf, funcName) != 0) {
207         if (asprintf(&func_message_buf, "%s: %s", funcName, message_buf) < 0)
208            func_message_buf = NULL;
209      }
210      _eglInternalError(error, func_message_buf ? func_message_buf : funcName);
211      free(func_message_buf);
212   }
213   free(message_buf);
214}
215