3 #include "eglcurrent.h"
4 #include "eglcontext.h"
7 #include "eglglobals.h"
10 /* This should be kept in sync with _eglInitThreadInfo() */
11 #define _EGL_THREAD_INFO_INITIALIZER \
12 { EGL_SUCCESS, { NULL }, 0 }
14 /* a fallback thread info to guarantee that every thread always has one */
15 static _EGLThreadInfo dummy_thread
= _EGL_THREAD_INFO_INITIALIZER
;
19 static __thread
const _EGLThreadInfo
*_egl_TSD
20 __attribute__ ((tls_model("initial-exec")));
22 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
27 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
29 return (_EGLThreadInfo
*) _egl_TSD
;
32 static INLINE
void _eglFiniTSD(void)
36 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
38 /* TODO destroy TSD */
47 static _EGL_DECLARE_MUTEX(_egl_TSDMutex
);
48 static EGLBoolean _egl_TSDInitialized
;
49 static pthread_key_t _egl_TSD
;
50 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
52 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
54 pthread_setspecific(_egl_TSD
, (const void *) t
);
57 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
59 return (_EGLThreadInfo
*) pthread_getspecific(_egl_TSD
);
62 static INLINE
void _eglFiniTSD(void)
64 _eglLockMutex(&_egl_TSDMutex
);
65 if (_egl_TSDInitialized
) {
66 _EGLThreadInfo
*t
= _eglGetTSD();
68 _egl_TSDInitialized
= EGL_FALSE
;
69 if (t
&& _egl_FreeTSD
)
70 _egl_FreeTSD((void *) t
);
71 pthread_key_delete(_egl_TSD
);
73 _eglUnlockMutex(&_egl_TSDMutex
);
76 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
78 if (!_egl_TSDInitialized
) {
79 _eglLockMutex(&_egl_TSDMutex
);
81 /* check again after acquiring lock */
82 if (!_egl_TSDInitialized
) {
83 if (pthread_key_create(&_egl_TSD
, (void (*)(void *)) dtor
) != 0) {
84 _eglUnlockMutex(&_egl_TSDMutex
);
88 _eglAddAtExitCall(_eglFiniTSD
);
89 _egl_TSDInitialized
= EGL_TRUE
;
92 _eglUnlockMutex(&_egl_TSDMutex
);
99 static const _EGLThreadInfo
*_egl_TSD
;
100 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
102 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
107 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
109 return (_EGLThreadInfo
*) _egl_TSD
;
112 static INLINE
void _eglFiniTSD(void)
114 if (_egl_FreeTSD
&& _egl_TSD
)
115 _egl_FreeTSD((_EGLThreadInfo
*) _egl_TSD
);
118 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
120 if (!_egl_FreeTSD
&& dtor
) {
122 _eglAddAtExitCall(_eglFiniTSD
);
127 #endif /* !PTHREADS */
131 _eglInitThreadInfo(_EGLThreadInfo
*t
)
133 memset(t
, 0, sizeof(*t
));
134 t
->LastError
= EGL_SUCCESS
;
135 /* default, per EGL spec */
136 t
->CurrentAPIIndex
= _eglConvertApiToIndex(EGL_OPENGL_ES_API
);
141 * Allocate and init a new _EGLThreadInfo object.
143 static _EGLThreadInfo
*
144 _eglCreateThreadInfo(void)
146 _EGLThreadInfo
*t
= (_EGLThreadInfo
*) calloc(1, sizeof(_EGLThreadInfo
));
148 _eglInitThreadInfo(t
);
156 * Delete/free a _EGLThreadInfo object.
159 _eglDestroyThreadInfo(_EGLThreadInfo
*t
)
161 if (t
!= &dummy_thread
)
167 * Make sure TSD is initialized and return current value.
169 static INLINE _EGLThreadInfo
*
170 _eglCheckedGetTSD(void)
172 if (_eglInitTSD(&_eglDestroyThreadInfo
) != EGL_TRUE
) {
173 _eglLog(_EGL_FATAL
, "failed to initialize \"current\" system");
182 * Return the calling thread's thread info.
183 * If the calling thread nevers calls this function before, or if its thread
184 * info was destroyed, a new one is created. This function never returns NULL.
185 * In the case allocation fails, a dummy one is returned. See also
186 * _eglIsCurrentThreadDummy.
189 _eglGetCurrentThread(void)
191 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
193 t
= _eglCreateThreadInfo();
202 * Destroy the calling thread's thread info.
205 _eglDestroyCurrentThread(void)
207 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
209 _eglDestroyThreadInfo(t
);
216 * Return true if the calling thread's thread info is dummy.
217 * A dummy thread info is shared by all threads and should not be modified.
218 * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness
219 * before updating the thread info.
222 _eglIsCurrentThreadDummy(void)
224 _EGLThreadInfo
*t
= _eglCheckedGetTSD();
225 return (!t
|| t
== &dummy_thread
);
230 * Return the currently bound context of the given API, or NULL.
233 _eglGetAPIContext(EGLenum api
)
235 _EGLThreadInfo
*t
= _eglGetCurrentThread();
236 return t
->CurrentContexts
[_eglConvertApiToIndex(api
)];
241 * Return the currently bound context of the current API, or NULL.
244 _eglGetCurrentContext(void)
246 _EGLThreadInfo
*t
= _eglGetCurrentThread();
247 return t
->CurrentContexts
[t
->CurrentAPIIndex
];
252 * Record EGL error code.
255 _eglError(EGLint errCode
, const char *msg
)
257 _EGLThreadInfo
*t
= _eglGetCurrentThread();
260 if (t
== &dummy_thread
)
263 if (t
->LastError
== EGL_SUCCESS
) {
264 t
->LastError
= errCode
;
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 case EGL_BAD_SCREEN_MESA
:
304 s
= "EGL_BAD_SCREEN_MESA";
306 case EGL_BAD_MODE_MESA
:
307 s
= "EGL_BAD_MODE_MESA";
312 _eglLog(_EGL_DEBUG
, "EGL user error 0x%x (%s) in %s\n", errCode
, s
, msg
);