xref: /aosp_15_r20/external/mesa3d/src/egl/main/eglcurrent.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2009-2010 Chia-I Wu <[email protected]>
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 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "c11/threads.h"
34 #include "util/u_string.h"
35 #include "util/u_thread.h"
36 
37 #include "eglcurrent.h"
38 #include "eglglobals.h"
39 #include "egllog.h"
40 
41 static __THREAD_INITIAL_EXEC _EGLThreadInfo _egl_TLS = {
42    .inited = false,
43 };
44 
45 static void
_eglInitThreadInfo(_EGLThreadInfo * t)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  * Return the calling thread's thread info.
55  * If the calling thread never calls this function before, or if its thread
56  * info was destroyed, reinitialize it.  This function never returns NULL.
57  */
58 _EGLThreadInfo *
_eglGetCurrentThread(void)59 _eglGetCurrentThread(void)
60 {
61    _EGLThreadInfo *current = &_egl_TLS;
62    if (unlikely(!current->inited)) {
63       memset(current, 0, sizeof(current[0]));
64       _eglInitThreadInfo(current);
65       current->inited = true;
66    }
67    return current;
68 }
69 
70 /**
71  * Destroy the calling thread's thread info.
72  */
73 void
_eglDestroyCurrentThread(void)74 _eglDestroyCurrentThread(void)
75 {
76    _EGLThreadInfo *t = _eglGetCurrentThread();
77    t->inited = false;
78 }
79 
80 /**
81  * Return the currently bound context of the current API, or NULL.
82  */
83 _EGLContext *
_eglGetCurrentContext(void)84 _eglGetCurrentContext(void)
85 {
86    _EGLThreadInfo *t = _eglGetCurrentThread();
87    return t->CurrentContext;
88 }
89 
90 /**
91  * Record EGL error code and return EGL_FALSE.
92  */
93 static EGLBoolean
_eglInternalError(EGLint errCode,const char * msg)94 _eglInternalError(EGLint errCode, const char *msg)
95 {
96    _EGLThreadInfo *t = _eglGetCurrentThread();
97 
98    t->LastError = errCode;
99 
100    if (errCode != EGL_SUCCESS) {
101       const char *s;
102 
103       switch (errCode) {
104       case EGL_BAD_ACCESS:
105          s = "EGL_BAD_ACCESS";
106          break;
107       case EGL_BAD_ALLOC:
108          s = "EGL_BAD_ALLOC";
109          break;
110       case EGL_BAD_ATTRIBUTE:
111          s = "EGL_BAD_ATTRIBUTE";
112          break;
113       case EGL_BAD_CONFIG:
114          s = "EGL_BAD_CONFIG";
115          break;
116       case EGL_BAD_CONTEXT:
117          s = "EGL_BAD_CONTEXT";
118          break;
119       case EGL_BAD_CURRENT_SURFACE:
120          s = "EGL_BAD_CURRENT_SURFACE";
121          break;
122       case EGL_BAD_DISPLAY:
123          s = "EGL_BAD_DISPLAY";
124          break;
125       case EGL_BAD_MATCH:
126          s = "EGL_BAD_MATCH";
127          break;
128       case EGL_BAD_NATIVE_PIXMAP:
129          s = "EGL_BAD_NATIVE_PIXMAP";
130          break;
131       case EGL_BAD_NATIVE_WINDOW:
132          s = "EGL_BAD_NATIVE_WINDOW";
133          break;
134       case EGL_BAD_PARAMETER:
135          s = "EGL_BAD_PARAMETER";
136          break;
137       case EGL_BAD_SURFACE:
138          s = "EGL_BAD_SURFACE";
139          break;
140       case EGL_NOT_INITIALIZED:
141          s = "EGL_NOT_INITIALIZED";
142          break;
143       default:
144          s = "other EGL error";
145       }
146       _eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
147    }
148 
149    return EGL_FALSE;
150 }
151 
152 EGLBoolean
_eglError(EGLint errCode,const char * msg)153 _eglError(EGLint errCode, const char *msg)
154 {
155    if (errCode != EGL_SUCCESS) {
156       EGLint type;
157       if (errCode == EGL_BAD_ALLOC)
158          type = EGL_DEBUG_MSG_CRITICAL_KHR;
159       else
160          type = EGL_DEBUG_MSG_ERROR_KHR;
161 
162       _eglDebugReport(errCode, NULL, type, msg);
163    } else
164       _eglInternalError(errCode, msg);
165 
166    return EGL_FALSE;
167 }
168 
169 void
_eglDebugReport(EGLenum error,const char * funcName,EGLint type,const char * message,...)170 _eglDebugReport(EGLenum error, const char *funcName, EGLint type,
171                 const char *message, ...)
172 {
173    _EGLThreadInfo *thr = _eglGetCurrentThread();
174    EGLDEBUGPROCKHR callback = NULL;
175    va_list args;
176 
177    if (funcName == NULL)
178       funcName = thr->CurrentFuncName;
179 
180    simple_mtx_lock(_eglGlobal.Mutex);
181    if (_eglGlobal.debugTypesEnabled & DebugBitFromType(type))
182       callback = _eglGlobal.debugCallback;
183 
184    simple_mtx_unlock(_eglGlobal.Mutex);
185 
186    char *message_buf = NULL;
187    if (message != NULL) {
188       va_start(args, message);
189       if (vasprintf(&message_buf, message, args) < 0)
190          message_buf = NULL;
191       va_end(args);
192    }
193 
194    if (callback != NULL) {
195       callback(error, funcName, type, thr->Label, thr->CurrentObjectLabel,
196                message_buf);
197    }
198 
199    if (type == EGL_DEBUG_MSG_CRITICAL_KHR || type == EGL_DEBUG_MSG_ERROR_KHR) {
200       char *func_message_buf = NULL;
201       /* Note: _eglError() is often called with msg == thr->currentFuncName */
202       if (message_buf && funcName && strcmp(message_buf, funcName) != 0) {
203          if (asprintf(&func_message_buf, "%s: %s", funcName, message_buf) < 0)
204             func_message_buf = NULL;
205       }
206       _eglInternalError(error, func_message_buf ? func_message_buf : funcName);
207       free(func_message_buf);
208    }
209    free(message_buf);
210 }
211