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
;
18 static __thread
const _EGLThreadInfo
*_egl_TSD
19 __attribute__ ((tls_model("initial-exec")));
21 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
26 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
28 return (_EGLThreadInfo
*) _egl_TSD
;
31 static INLINE
void _eglFiniTSD(void)
35 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
37 /* TODO destroy TSD */
46 static _EGL_DECLARE_MUTEX(_egl_TSDMutex
);
47 static EGLBoolean _egl_TSDInitialized
;
48 static pthread_key_t _egl_TSD
;
49 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
51 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
53 pthread_setspecific(_egl_TSD
, (const void *) t
);
56 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
58 return (_EGLThreadInfo
*) pthread_getspecific(_egl_TSD
);
61 static INLINE
void _eglFiniTSD(void)
63 _eglLockMutex(&_egl_TSDMutex
);
64 if (_egl_TSDInitialized
) {
65 _EGLThreadInfo
*t
= _eglGetTSD();
67 _egl_TSDInitialized
= EGL_FALSE
;
68 if (t
&& _egl_FreeTSD
)
69 _egl_FreeTSD((void *) t
);
70 pthread_key_delete(_egl_TSD
);
72 _eglUnlockMutex(&_egl_TSDMutex
);
75 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
77 if (!_egl_TSDInitialized
) {
78 _eglLockMutex(&_egl_TSDMutex
);
80 /* check again after acquiring lock */
81 if (!_egl_TSDInitialized
) {
82 if (pthread_key_create(&_egl_TSD
, (void (*)(void *)) dtor
) != 0) {
83 _eglUnlockMutex(&_egl_TSDMutex
);
87 _eglAddAtExitCall(_eglFiniTSD
);
88 _egl_TSDInitialized
= EGL_TRUE
;
91 _eglUnlockMutex(&_egl_TSDMutex
);
98 static const _EGLThreadInfo
*_egl_TSD
;
99 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
101 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
106 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
108 return (_EGLThreadInfo
*) _egl_TSD
;
111 static INLINE
void _eglFiniTSD(void)
113 if (_egl_FreeTSD
&& _egl_TSD
)
114 _egl_FreeTSD((_EGLThreadInfo
*) _egl_TSD
);
117 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
119 if (!_egl_FreeTSD
&& dtor
) {
121 _eglAddAtExitCall(_eglFiniTSD
);
126 #endif /* !PTHREADS */
130 _eglInitThreadInfo(_EGLThreadInfo
*t
)
132 memset(t
, 0, sizeof(*t
));
133 t
->LastError
= EGL_SUCCESS
;
134 /* default, per EGL spec */
135 t
->CurrentAPIIndex
= _eglConvertApiToIndex(EGL_OPENGL_ES_API
);
140 * Allocate and init a new _EGLThreadInfo object.
142 static _EGLThreadInfo
*
143 _eglCreateThreadInfo(void)
145 _EGLThreadInfo
*t
= (_EGLThreadInfo
*) calloc(1, sizeof(_EGLThreadInfo
));
147 _eglInitThreadInfo(t
);
155 * Delete/free a _EGLThreadInfo object.
158 _eglDestroyThreadInfo(_EGLThreadInfo
*t
)
160 if (t
!= &dummy_thread
)
166 * Make sure TSD is initialized and return current value.
168 static INLINE _EGLThreadInfo
*
169 _eglCheckedGetTSD(void)
171 if (_eglInitTSD(&_eglDestroyThreadInfo
) != EGL_TRUE
) {
172 _eglLog(_EGL_FATAL
, "failed to initialize \"current\" system");
181 * Return the calling thread's thread info.
182 * If the calling thread nevers calls this function before, or if its thread
183 * info was destroyed, a new one is created. This function never returns NULL.
184 * In the case allocation fails, a dummy one is returned. See also
185 * _eglIsCurrentThreadDummy.
188 _eglGetCurrentThread(void)
190 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
192 t
= _eglCreateThreadInfo();
201 * Destroy the calling thread's thread info.
204 _eglDestroyCurrentThread(void)
206 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
208 _eglDestroyThreadInfo(t
);
215 * Return true if the calling thread's thread info is dummy.
216 * A dummy thread info is shared by all threads and should not be modified.
217 * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness
218 * before updating the thread info.
221 _eglIsCurrentThreadDummy(void)
223 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
224 return (!t
|| t
== &dummy_thread
);
229 * Return the currently bound context of the given API, or NULL.
232 _eglGetAPIContext(EGLenum api
)
234 _EGLThreadInfo
*t
= _eglGetCurrentThread();
235 return t
->CurrentContexts
[_eglConvertApiToIndex(api
)];
240 * Return the currently bound context of the current API, or NULL.
243 _eglGetCurrentContext(void)
245 _EGLThreadInfo
*t
= _eglGetCurrentThread();
246 return t
->CurrentContexts
[t
->CurrentAPIIndex
];
251 * Record EGL error code and return EGL_FALSE.
254 _eglError(EGLint errCode
, const char *msg
)
256 _EGLThreadInfo
*t
= _eglGetCurrentThread();
258 if (t
== &dummy_thread
)
261 t
->LastError
= errCode
;
263 if (errCode
!= EGL_SUCCESS
) {
268 s
= "EGL_BAD_ACCESS";
273 case EGL_BAD_ATTRIBUTE
:
274 s
= "EGL_BAD_ATTRIBUTE";
277 s
= "EGL_BAD_CONFIG";
279 case EGL_BAD_CONTEXT
:
280 s
= "EGL_BAD_CONTEXT";
282 case EGL_BAD_CURRENT_SURFACE
:
283 s
= "EGL_BAD_CURRENT_SURFACE";
285 case EGL_BAD_DISPLAY
:
286 s
= "EGL_BAD_DISPLAY";
291 case EGL_BAD_NATIVE_PIXMAP
:
292 s
= "EGL_BAD_NATIVE_PIXMAP";
294 case EGL_BAD_NATIVE_WINDOW
:
295 s
= "EGL_BAD_NATIVE_WINDOW";
297 case EGL_BAD_PARAMETER
:
298 s
= "EGL_BAD_PARAMETER";
300 case EGL_BAD_SURFACE
:
301 s
= "EGL_BAD_SURFACE";
303 #ifdef EGL_MESA_screen_surface
304 case EGL_BAD_SCREEN_MESA
:
305 s
= "EGL_BAD_SCREEN_MESA";
307 case EGL_BAD_MODE_MESA
:
308 s
= "EGL_BAD_MODE_MESA";
314 _eglLog(_EGL_DEBUG
, "EGL user error 0x%x (%s) in %s\n", errCode
, s
, msg
);