3 #include "eglcurrent.h"
4 #include "eglcontext.h"
9 /* a fallback thread info to guarantee that every thread always has one */
10 static _EGLThreadInfo dummy_thread
;
14 static __thread
const _EGLThreadInfo
*_egl_TSD
;
15 __attribute__ ((tls_model("initial-exec")));
17 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
22 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
24 return (_EGLThreadInfo
*) _egl_TSD
;
27 static INLINE
void _eglFiniTSD(void)
31 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
33 /* TODO destroy TSD */
41 static _EGL_DECLARE_MUTEX(_egl_TSDMutex
);
42 static EGLBoolean _egl_TSDInitialized
;
43 static pthread_key_t _egl_TSD
;
44 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
46 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
48 pthread_setspecific(_egl_TSD
, (const void *) t
);
51 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
53 return (_EGLThreadInfo
*) pthread_getspecific(_egl_TSD
);
56 static INLINE
void _eglFiniTSD(void)
58 _eglLockMutex(&_egl_TSDMutex
);
59 if (_egl_TSDInitialized
) {
60 _EGLThreadInfo
*t
= _eglGetTSD();
62 _egl_TSDInitialized
= EGL_FALSE
;
63 if (t
&& _egl_FreeTSD
)
64 _egl_FreeTSD((void *) t
);
65 pthread_key_delete(_egl_TSD
);
67 _eglUnlockMutex(&_egl_TSDMutex
);
70 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
72 if (!_egl_TSDInitialized
) {
73 _eglLockMutex(&_egl_TSDMutex
);
75 /* check again after acquiring lock */
76 if (!_egl_TSDInitialized
) {
77 if (pthread_key_create(&_egl_TSD
, (void (*)(void *)) dtor
) != 0) {
78 _eglUnlockMutex(&_egl_TSDMutex
);
82 _egl_TSDInitialized
= EGL_TRUE
;
85 _eglUnlockMutex(&_egl_TSDMutex
);
92 static const _EGLThreadInfo
*_egl_TSD
;
93 static void (*_egl_FreeTSD
)(_EGLThreadInfo
*);
95 static INLINE
void _eglSetTSD(const _EGLThreadInfo
*t
)
100 static INLINE _EGLThreadInfo
*_eglGetTSD(void)
102 return (_EGLThreadInfo
*) _egl_TSD
;
105 static INLINE
void _eglFiniTSD(void)
107 if (_egl_FreeTSD
&& _egl_TSD
)
108 _egl_FreeTSD((_EGLThreadInfo
*) _egl_TSD
);
111 static INLINE EGLBoolean
_eglInitTSD(void (*dtor
)(_EGLThreadInfo
*))
113 if (!_egl_FreeTSD
&& dtor
) {
119 #endif /* !PTHREADS */
123 _eglInitThreadInfo(_EGLThreadInfo
*t
)
125 memset(t
, 0, sizeof(*t
));
126 t
->LastError
= EGL_SUCCESS
;
127 /* default, per EGL spec */
128 t
->CurrentAPIIndex
= _eglConvertApiToIndex(EGL_OPENGL_ES_API
);
133 * Allocate and init a new _EGLThreadInfo object.
135 static _EGLThreadInfo
*
136 _eglCreateThreadInfo(void)
138 _EGLThreadInfo
*t
= (_EGLThreadInfo
*) calloc(1, sizeof(_EGLThreadInfo
));
140 _eglInitThreadInfo(t
);
148 * Delete/free a _EGLThreadInfo object.
151 _eglDestroyThreadInfo(_EGLThreadInfo
*t
)
153 if (t
!= &dummy_thread
)
159 * Initialize "current thread" management.
162 _eglInitCurrent(void)
164 _eglInitThreadInfo(&dummy_thread
);
165 return _eglInitTSD((void (*)(void *)) _eglDestroyThreadInfo
);
170 * Finish "current thread" management.
173 _eglFiniCurrent(void)
180 * Return the calling thread's thread info.
181 * If the calling thread nevers calls this function before, or if its thread
182 * info was destroyed, a new one is created. This function never returns NULL.
183 * In the case allocation fails, a dummy one is returned. See also
184 * _eglIsCurrentThreadDummy.
187 _eglGetCurrentThread(void)
189 _EGLThreadInfo
*t
= _eglGetTSD();
191 t
= _eglCreateThreadInfo();
200 * Destroy the calling thread's thread info.
203 _eglDestroyCurrentThread(void)
205 _EGLThreadInfo
*t
= _eglGetTSD();
207 _eglDestroyThreadInfo(t
);
214 * Return true if the calling thread's thread info is dummy.
215 * A dummy thread info is shared by all threads and should not be modified.
216 * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness
217 * before updating the thread info.
220 _eglIsCurrentThreadDummy(void)
222 _EGLThreadInfo
*t
= _eglGetTSD();
223 return (!t
|| t
== &dummy_thread
);
228 * Return the currently bound context, or NULL.
231 _eglGetCurrentContext(void)
233 _EGLThreadInfo
*t
= _eglGetCurrentThread();
234 return t
->CurrentContexts
[t
->CurrentAPIIndex
];
239 * Return the display of the currently bound context, or NULL.
242 _eglGetCurrentDisplay(void)
244 _EGLThreadInfo
*t
= _eglGetCurrentThread();
245 _EGLContext
*ctx
= t
->CurrentContexts
[t
->CurrentAPIIndex
];
254 * Return the read or write surface of the currently bound context, or NULL.
257 _eglGetCurrentSurface(EGLint readdraw
)
259 _EGLThreadInfo
*t
= _eglGetCurrentThread();
260 _EGLContext
*ctx
= t
->CurrentContexts
[t
->CurrentAPIIndex
];
264 return ctx
->DrawSurface
;
266 return ctx
->ReadSurface
;
276 * Record EGL error code.
279 _eglError(EGLint errCode
, const char *msg
)
281 _EGLThreadInfo
*t
= _eglGetCurrentThread();
284 if (t
== &dummy_thread
)
287 if (t
->LastError
== EGL_SUCCESS
) {
288 t
->LastError
= errCode
;
292 s
= "EGL_BAD_ACCESS";
297 case EGL_BAD_ATTRIBUTE
:
298 s
= "EGL_BAD_ATTRIBUTE";
301 s
= "EGL_BAD_CONFIG";
303 case EGL_BAD_CONTEXT
:
304 s
= "EGL_BAD_CONTEXT";
306 case EGL_BAD_CURRENT_SURFACE
:
307 s
= "EGL_BAD_CURRENT_SURFACE";
309 case EGL_BAD_DISPLAY
:
310 s
= "EGL_BAD_DISPLAY";
315 case EGL_BAD_NATIVE_PIXMAP
:
316 s
= "EGL_BAD_NATIVE_PIXMAP";
318 case EGL_BAD_NATIVE_WINDOW
:
319 s
= "EGL_BAD_NATIVE_WINDOW";
321 case EGL_BAD_PARAMETER
:
322 s
= "EGL_BAD_PARAMETER";
324 case EGL_BAD_SURFACE
:
325 s
= "EGL_BAD_SURFACE";
327 case EGL_BAD_SCREEN_MESA
:
328 s
= "EGL_BAD_SCREEN_MESA";
330 case EGL_BAD_MODE_MESA
:
331 s
= "EGL_BAD_MODE_MESA";
336 _eglLog(_EGL_DEBUG
, "EGL user error 0x%x (%s) in %s\n", errCode
, s
, msg
);