Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / libs / mesa / src / egl / main / eglcurrent.c
blob16e344cdbf67e09a745477b3ee79bd8dd897ff27
1 /**************************************************************************
3 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
4 * All Rights Reserved.
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:
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.
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.
26 **************************************************************************/
29 #include <stdlib.h>
30 #include <string.h>
31 #include "egllog.h"
32 #include "eglmutex.h"
33 #include "eglcurrent.h"
34 #include "eglglobals.h"
37 /* This should be kept in sync with _eglInitThreadInfo() */
38 #define _EGL_THREAD_INFO_INITIALIZER \
39 { EGL_SUCCESS, { NULL }, 0 }
41 /* a fallback thread info to guarantee that every thread always has one */
42 static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER;
45 #if PTHREADS
46 #include <pthread.h>
48 static _EGL_DECLARE_MUTEX(_egl_TSDMutex);
49 static EGLBoolean _egl_TSDInitialized;
50 static pthread_key_t _egl_TSD;
51 static void (*_egl_FreeTSD)(_EGLThreadInfo *);
53 #ifdef GLX_USE_TLS
54 static __thread const _EGLThreadInfo *_egl_TLS
55 __attribute__ ((tls_model("initial-exec")));
56 #endif
58 static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
60 pthread_setspecific(_egl_TSD, (const void *) t);
61 #ifdef GLX_USE_TLS
62 _egl_TLS = t;
63 #endif
66 static INLINE _EGLThreadInfo *_eglGetTSD(void)
68 #ifdef GLX_USE_TLS
69 return (_EGLThreadInfo *) _egl_TLS;
70 #else
71 return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD);
72 #endif
75 static INLINE void _eglFiniTSD(void)
77 _eglLockMutex(&_egl_TSDMutex);
78 if (_egl_TSDInitialized) {
79 _EGLThreadInfo *t = _eglGetTSD();
81 _egl_TSDInitialized = EGL_FALSE;
82 if (t && _egl_FreeTSD)
83 _egl_FreeTSD((void *) t);
84 pthread_key_delete(_egl_TSD);
86 _eglUnlockMutex(&_egl_TSDMutex);
89 static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
91 if (!_egl_TSDInitialized) {
92 _eglLockMutex(&_egl_TSDMutex);
94 /* check again after acquiring lock */
95 if (!_egl_TSDInitialized) {
96 if (pthread_key_create(&_egl_TSD, (void (*)(void *)) dtor) != 0) {
97 _eglUnlockMutex(&_egl_TSDMutex);
98 return EGL_FALSE;
100 _egl_FreeTSD = dtor;
101 _eglAddAtExitCall(_eglFiniTSD);
102 _egl_TSDInitialized = EGL_TRUE;
105 _eglUnlockMutex(&_egl_TSDMutex);
108 return EGL_TRUE;
111 #elif defined(_EGL_OS_AROS)
113 #include "aros/tls.h"
115 static struct TaskLocalStorage * tls = NULL;
116 static void (*_egl_FreeTSD)(_EGLThreadInfo *);
118 static INLINE void _eglFiniTSD(void)
120 DestroyTLS(tls);
123 static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
125 InsertIntoTLS(tls, (APTR)t);
128 static INLINE _EGLThreadInfo *_eglGetTSD(void)
130 return (_EGLThreadInfo *)GetFromTLS(tls);
133 static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
135 if (!tls)
137 tls = CreateTLS();
138 _egl_FreeTSD = dtor;
139 _eglAddAtExitCall(_eglFiniTSD);
142 if (tls)
143 return EGL_TRUE;
144 else
145 return EGL_FALSE;
148 #include <aros/symbolsets.h>
150 static VOID _egl_FreeTSD_fn()
152 _EGLThreadInfo *t = NULL;
154 if (!tls) return;
156 t = _eglGetTSD();
158 if (t && _egl_FreeTSD)
159 _egl_FreeTSD((void *) t);
160 ClearFromTLS(tls);
162 ADD2CLOSELIB(_egl_FreeTSD_fn, 10)
164 #else /* PTHREADS */
165 static const _EGLThreadInfo *_egl_TSD;
166 static void (*_egl_FreeTSD)(_EGLThreadInfo *);
168 static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
170 _egl_TSD = t;
173 static INLINE _EGLThreadInfo *_eglGetTSD(void)
175 return (_EGLThreadInfo *) _egl_TSD;
178 static INLINE void _eglFiniTSD(void)
180 if (_egl_FreeTSD && _egl_TSD)
181 _egl_FreeTSD((_EGLThreadInfo *) _egl_TSD);
184 static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *))
186 if (!_egl_FreeTSD && dtor) {
187 _egl_FreeTSD = dtor;
188 _eglAddAtExitCall(_eglFiniTSD);
190 return EGL_TRUE;
193 #endif /* !PTHREADS */
196 static void
197 _eglInitThreadInfo(_EGLThreadInfo *t)
199 memset(t, 0, sizeof(*t));
200 t->LastError = EGL_SUCCESS;
201 /* default, per EGL spec */
202 t->CurrentAPIIndex = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
207 * Allocate and init a new _EGLThreadInfo object.
209 static _EGLThreadInfo *
210 _eglCreateThreadInfo(void)
212 _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo));
213 if (t)
214 _eglInitThreadInfo(t);
215 else
216 t = &dummy_thread;
217 return t;
222 * Delete/free a _EGLThreadInfo object.
224 static void
225 _eglDestroyThreadInfo(_EGLThreadInfo *t)
227 if (t != &dummy_thread)
228 free(t);
233 * Make sure TSD is initialized and return current value.
235 static INLINE _EGLThreadInfo *
236 _eglCheckedGetTSD(void)
238 if (_eglInitTSD(&_eglDestroyThreadInfo) != EGL_TRUE) {
239 _eglLog(_EGL_FATAL, "failed to initialize \"current\" system");
240 return NULL;
243 return _eglGetTSD();
248 * Return the calling thread's thread info.
249 * If the calling thread nevers calls this function before, or if its thread
250 * info was destroyed, a new one is created. This function never returns NULL.
251 * In the case allocation fails, a dummy one is returned. See also
252 * _eglIsCurrentThreadDummy.
254 _EGLThreadInfo *
255 _eglGetCurrentThread(void)
257 _EGLThreadInfo *t = _eglCheckedGetTSD();
258 if (!t) {
259 t = _eglCreateThreadInfo();
260 _eglSetTSD(t);
263 return t;
268 * Destroy the calling thread's thread info.
270 void
271 _eglDestroyCurrentThread(void)
273 _EGLThreadInfo *t = _eglCheckedGetTSD();
274 if (t) {
275 _eglDestroyThreadInfo(t);
276 _eglSetTSD(NULL);
282 * Return true if the calling thread's thread info is dummy.
283 * A dummy thread info is shared by all threads and should not be modified.
284 * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness
285 * before updating the thread info.
287 EGLBoolean
288 _eglIsCurrentThreadDummy(void)
290 _EGLThreadInfo *t = _eglCheckedGetTSD();
291 return (!t || t == &dummy_thread);
296 * Return the currently bound context of the given API, or NULL.
298 PUBLIC _EGLContext *
299 _eglGetAPIContext(EGLenum api)
301 _EGLThreadInfo *t = _eglGetCurrentThread();
302 return t->CurrentContexts[_eglConvertApiToIndex(api)];
307 * Return the currently bound context of the current API, or NULL.
309 _EGLContext *
310 _eglGetCurrentContext(void)
312 _EGLThreadInfo *t = _eglGetCurrentThread();
313 return t->CurrentContexts[t->CurrentAPIIndex];
318 * Record EGL error code and return EGL_FALSE.
320 EGLBoolean
321 _eglError(EGLint errCode, const char *msg)
323 _EGLThreadInfo *t = _eglGetCurrentThread();
325 if (t == &dummy_thread)
326 return EGL_FALSE;
328 t->LastError = errCode;
330 if (errCode != EGL_SUCCESS) {
331 const char *s;
333 switch (errCode) {
334 case EGL_BAD_ACCESS:
335 s = "EGL_BAD_ACCESS";
336 break;
337 case EGL_BAD_ALLOC:
338 s = "EGL_BAD_ALLOC";
339 break;
340 case EGL_BAD_ATTRIBUTE:
341 s = "EGL_BAD_ATTRIBUTE";
342 break;
343 case EGL_BAD_CONFIG:
344 s = "EGL_BAD_CONFIG";
345 break;
346 case EGL_BAD_CONTEXT:
347 s = "EGL_BAD_CONTEXT";
348 break;
349 case EGL_BAD_CURRENT_SURFACE:
350 s = "EGL_BAD_CURRENT_SURFACE";
351 break;
352 case EGL_BAD_DISPLAY:
353 s = "EGL_BAD_DISPLAY";
354 break;
355 case EGL_BAD_MATCH:
356 s = "EGL_BAD_MATCH";
357 break;
358 case EGL_BAD_NATIVE_PIXMAP:
359 s = "EGL_BAD_NATIVE_PIXMAP";
360 break;
361 case EGL_BAD_NATIVE_WINDOW:
362 s = "EGL_BAD_NATIVE_WINDOW";
363 break;
364 case EGL_BAD_PARAMETER:
365 s = "EGL_BAD_PARAMETER";
366 break;
367 case EGL_BAD_SURFACE:
368 s = "EGL_BAD_SURFACE";
369 break;
370 case EGL_NOT_INITIALIZED:
371 s = "EGL_NOT_INITIALIZED";
372 break;
373 #ifdef EGL_MESA_screen_surface
374 case EGL_BAD_SCREEN_MESA:
375 s = "EGL_BAD_SCREEN_MESA";
376 break;
377 case EGL_BAD_MODE_MESA:
378 s = "EGL_BAD_MODE_MESA";
379 break;
380 #endif
381 default:
382 s = "other EGL error";
384 _eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
387 return EGL_FALSE;