5 #include "eglcurrent.h"
6 #include "eglglobals.h"
9 /* This should be kept in sync with _eglInitThreadInfo() */
10 #define _EGL_THREAD_INFO_INITIALIZER \
11 { EGL_SUCCESS, { NULL }, 0 }
13 /* a fallback thread info to guarantee that every thread always has one */
14 static _EGLThreadInfo dummy_thread
= _EGL_THREAD_INFO_INITIALIZER
;
20 static _EGL_DECLARE_MUTEX(_egl_TSDMutex
);
21 static EGLBoolean _egl_TSDInitialized
;
22 static pthread_key_t _egl_TSD
;
23 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
26 static __thread
const _EGLThreadInfo
*_egl_TLS
27 __attribute__ ((tls_model("initial-exec")));
30 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
32 pthread_setspecific(_egl_TSD
, (const void *) t
);
38 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
41 return (_EGLThreadInfo
*) _egl_TLS
;
43 return (_EGLThreadInfo
*) pthread_getspecific(_egl_TSD
);
47 static INLINE
void _eglFiniTSD(void)
49 _eglLockMutex(&_egl_TSDMutex
);
50 if (_egl_TSDInitialized
) {
51 _EGLThreadInfo
*t
= _eglGetTSD();
53 _egl_TSDInitialized
= EGL_FALSE
;
54 if (t
&& _egl_FreeTSD
)
55 _egl_FreeTSD((void *) t
);
56 pthread_key_delete(_egl_TSD
);
58 _eglUnlockMutex(&_egl_TSDMutex
);
61 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
63 if (!_egl_TSDInitialized
) {
64 _eglLockMutex(&_egl_TSDMutex
);
66 /* check again after acquiring lock */
67 if (!_egl_TSDInitialized
) {
68 if (pthread_key_create(&_egl_TSD
, (void (*)(void *)) dtor
) != 0) {
69 _eglUnlockMutex(&_egl_TSDMutex
);
73 _eglAddAtExitCall(_eglFiniTSD
);
74 _egl_TSDInitialized
= EGL_TRUE
;
77 _eglUnlockMutex(&_egl_TSDMutex
);
84 static const _EGLThreadInfo
*_egl_TSD
;
85 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
87 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
92 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
94 return (_EGLThreadInfo
*) _egl_TSD
;
97 static INLINE
void _eglFiniTSD(void)
99 if (_egl_FreeTSD
&& _egl_TSD
)
100 _egl_FreeTSD((_EGLThreadInfo
*) _egl_TSD
);
103 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
105 if (!_egl_FreeTSD
&& dtor
) {
107 _eglAddAtExitCall(_eglFiniTSD
);
112 #endif /* !PTHREADS */
116 _eglInitThreadInfo(_EGLThreadInfo
*t
)
118 memset(t
, 0, sizeof(*t
));
119 t
->LastError
= EGL_SUCCESS
;
120 /* default, per EGL spec */
121 t
->CurrentAPIIndex
= _eglConvertApiToIndex(EGL_OPENGL_ES_API
);
126 * Allocate and init a new _EGLThreadInfo object.
128 static _EGLThreadInfo
*
129 _eglCreateThreadInfo(void)
131 _EGLThreadInfo
*t
= (_EGLThreadInfo
*) calloc(1, sizeof(_EGLThreadInfo
));
133 _eglInitThreadInfo(t
);
141 * Delete/free a _EGLThreadInfo object.
144 _eglDestroyThreadInfo(_EGLThreadInfo
*t
)
146 if (t
!= &dummy_thread
)
152 * Make sure TSD is initialized and return current value.
154 static INLINE _EGLThreadInfo
*
155 _eglCheckedGetTSD(void)
157 if (_eglInitTSD(&_eglDestroyThreadInfo
) != EGL_TRUE
) {
158 _eglLog(_EGL_FATAL
, "failed to initialize \"current\" system");
167 * Return the calling thread's thread info.
168 * If the calling thread nevers calls this function before, or if its thread
169 * info was destroyed, a new one is created. This function never returns NULL.
170 * In the case allocation fails, a dummy one is returned. See also
171 * _eglIsCurrentThreadDummy.
174 _eglGetCurrentThread(void)
176 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
178 t
= _eglCreateThreadInfo();
187 * Destroy the calling thread's thread info.
190 _eglDestroyCurrentThread(void)
192 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
194 _eglDestroyThreadInfo(t
);
201 * Return true if the calling thread's thread info is dummy.
202 * A dummy thread info is shared by all threads and should not be modified.
203 * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness
204 * before updating the thread info.
207 _eglIsCurrentThreadDummy(void)
209 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
210 return (!t
|| t
== &dummy_thread
);
215 * Return the currently bound context of the given API, or NULL.
218 _eglGetAPIContext(EGLenum api
)
220 _EGLThreadInfo
*t
= _eglGetCurrentThread();
221 return t
->CurrentContexts
[_eglConvertApiToIndex(api
)];
226 * Return the currently bound context of the current API, or NULL.
229 _eglGetCurrentContext(void)
231 _EGLThreadInfo
*t
= _eglGetCurrentThread();
232 return t
->CurrentContexts
[t
->CurrentAPIIndex
];
237 * Record EGL error code and return EGL_FALSE.
240 _eglError(EGLint errCode
, const char *msg
)
242 _EGLThreadInfo
*t
= _eglGetCurrentThread();
244 if (t
== &dummy_thread
)
247 t
->LastError
= errCode
;
249 if (errCode
!= EGL_SUCCESS
) {
254 s
= "EGL_BAD_ACCESS";
259 case EGL_BAD_ATTRIBUTE
:
260 s
= "EGL_BAD_ATTRIBUTE";
263 s
= "EGL_BAD_CONFIG";
265 case EGL_BAD_CONTEXT
:
266 s
= "EGL_BAD_CONTEXT";
268 case EGL_BAD_CURRENT_SURFACE
:
269 s
= "EGL_BAD_CURRENT_SURFACE";
271 case EGL_BAD_DISPLAY
:
272 s
= "EGL_BAD_DISPLAY";
277 case EGL_BAD_NATIVE_PIXMAP
:
278 s
= "EGL_BAD_NATIVE_PIXMAP";
280 case EGL_BAD_NATIVE_WINDOW
:
281 s
= "EGL_BAD_NATIVE_WINDOW";
283 case EGL_BAD_PARAMETER
:
284 s
= "EGL_BAD_PARAMETER";
286 case EGL_BAD_SURFACE
:
287 s
= "EGL_BAD_SURFACE";
289 case EGL_NOT_INITIALIZED
:
290 s
= "EGL_NOT_INITIALIZED";
292 #ifdef EGL_MESA_screen_surface
293 case EGL_BAD_SCREEN_MESA
:
294 s
= "EGL_BAD_SCREEN_MESA";
296 case EGL_BAD_MODE_MESA
:
297 s
= "EGL_BAD_MODE_MESA";
301 s
= "other EGL error";
303 _eglLog(_EGL_DEBUG
, "EGL user error 0x%x (%s) in %s\n", errCode
, s
, msg
);