egl: Remove _eglGetCurrentSurface and _eglGetCurrentDisplay.
[mesa/nouveau-pmpeg.git] / src / egl / main / eglcurrent.c
blob696d04e8ba9fc1a3f1624df71f0c78892ba1ff64
1 #include <stdlib.h>
2 #include <string.h>
3 #include "eglcurrent.h"
4 #include "eglcontext.h"
5 #include "egllog.h"
6 #include "eglmutex.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;
18 #ifdef GLX_USE_TLS
19 static __thread const _EGLThreadInfo *_egl_TSD
20 __attribute__ ((tls_model("initial-exec")));
22 static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
24 _egl_TSD = 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 */
39 (void) dtor;
40 (void) _eglFiniTSD;
41 return EGL_TRUE;
44 #elif PTHREADS
45 #include <pthread.h>
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);
85 return EGL_FALSE;
87 _egl_FreeTSD = dtor;
88 _eglAddAtExitCall(_eglFiniTSD);
89 _egl_TSDInitialized = EGL_TRUE;
92 _eglUnlockMutex(&_egl_TSDMutex);
95 return EGL_TRUE;
98 #else /* PTHREADS */
99 static const _EGLThreadInfo *_egl_TSD;
100 static void (*_egl_FreeTSD)(_EGLThreadInfo *);
102 static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
104 _egl_TSD = 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) {
121 _egl_FreeTSD = dtor;
122 _eglAddAtExitCall(_eglFiniTSD);
124 return EGL_TRUE;
127 #endif /* !PTHREADS */
130 static void
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));
147 if (t)
148 _eglInitThreadInfo(t);
149 else
150 t = &dummy_thread;
151 return t;
156 * Delete/free a _EGLThreadInfo object.
158 static void
159 _eglDestroyThreadInfo(_EGLThreadInfo *t)
161 if (t != &dummy_thread)
162 free(t);
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");
174 return NULL;
177 return _eglGetTSD();
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.
188 _EGLThreadInfo *
189 _eglGetCurrentThread(void)
191 _EGLThreadInfo *t = _eglCheckedGetTSD();
192 if (!t) {
193 t = _eglCreateThreadInfo();
194 _eglSetTSD(t);
197 return t;
202 * Destroy the calling thread's thread info.
204 void
205 _eglDestroyCurrentThread(void)
207 _EGLThreadInfo *t = _eglCheckedGetTSD();
208 if (t) {
209 _eglDestroyThreadInfo(t);
210 _eglSetTSD(NULL);
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.
221 EGLBoolean
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.
232 PUBLIC _EGLContext *
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.
243 _EGLContext *
244 _eglGetCurrentContext(void)
246 _EGLThreadInfo *t = _eglGetCurrentThread();
247 return t->CurrentContexts[t->CurrentAPIIndex];
252 * Record EGL error code.
254 EGLBoolean
255 _eglError(EGLint errCode, const char *msg)
257 _EGLThreadInfo *t = _eglGetCurrentThread();
258 const char *s;
260 if (t == &dummy_thread)
261 return EGL_FALSE;
263 if (t->LastError == EGL_SUCCESS) {
264 t->LastError = errCode;
266 switch (errCode) {
267 case EGL_BAD_ACCESS:
268 s = "EGL_BAD_ACCESS";
269 break;
270 case EGL_BAD_ALLOC:
271 s = "EGL_BAD_ALLOC";
272 break;
273 case EGL_BAD_ATTRIBUTE:
274 s = "EGL_BAD_ATTRIBUTE";
275 break;
276 case EGL_BAD_CONFIG:
277 s = "EGL_BAD_CONFIG";
278 break;
279 case EGL_BAD_CONTEXT:
280 s = "EGL_BAD_CONTEXT";
281 break;
282 case EGL_BAD_CURRENT_SURFACE:
283 s = "EGL_BAD_CURRENT_SURFACE";
284 break;
285 case EGL_BAD_DISPLAY:
286 s = "EGL_BAD_DISPLAY";
287 break;
288 case EGL_BAD_MATCH:
289 s = "EGL_BAD_MATCH";
290 break;
291 case EGL_BAD_NATIVE_PIXMAP:
292 s = "EGL_BAD_NATIVE_PIXMAP";
293 break;
294 case EGL_BAD_NATIVE_WINDOW:
295 s = "EGL_BAD_NATIVE_WINDOW";
296 break;
297 case EGL_BAD_PARAMETER:
298 s = "EGL_BAD_PARAMETER";
299 break;
300 case EGL_BAD_SURFACE:
301 s = "EGL_BAD_SURFACE";
302 break;
303 case EGL_BAD_SCREEN_MESA:
304 s = "EGL_BAD_SCREEN_MESA";
305 break;
306 case EGL_BAD_MODE_MESA:
307 s = "EGL_BAD_MODE_MESA";
308 break;
309 default:
310 s = "other";
312 _eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
315 return EGL_FALSE;