This commit introduces a "current" system to manage per-thread info. It uses TLS, if GLX_USE_TLS is defined, or pthread, if PTHREADS is defined. If none of them are defined, it uses a dummy implementation that is just like before.
Signed-off-by: Chia-I Wu <[email protected]> --- configs/default | 2 +- src/egl/main/Makefile | 2 + src/egl/main/eglapi.c | 16 ++- src/egl/main/eglcontext.c | 14 +-- src/egl/main/eglcontext.h | 4 - src/egl/main/eglcurrent.c | 261 +++++++++++++++++++++++++++++++++++++++++++++ src/egl/main/eglcurrent.h | 55 ++++++++++ src/egl/main/egldisplay.c | 11 -- src/egl/main/egldisplay.h | 4 - src/egl/main/eglglobals.c | 113 +------------------- src/egl/main/eglglobals.h | 33 +------ src/egl/main/eglsurface.c | 18 --- src/egl/main/eglsurface.h | 4 - 13 files changed, 340 insertions(+), 197 deletions(-) create mode 100644 src/egl/main/eglcurrent.c create mode 100644 src/egl/main/eglcurrent.h diff --git a/configs/default b/configs/default index a899670..60638d7 100644 --- a/configs/default +++ b/configs/default @@ -105,7 +105,7 @@ GALLIUM_STATE_TRACKERS_DIRS = glx # Library dependencies #EXTRA_LIB_PATH ?= GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -ldl +EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -ldl -lpthread OSMESA_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) GLU_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -lm GLUT_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GLU_LIB) -l$(GL_LIB) -lX11 -lXmu -lXi -lm diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index cddba9f..3a9c35f 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile @@ -10,6 +10,7 @@ HEADERS = \ eglconfig.h \ eglconfigutil.h \ eglcontext.h \ + eglcurrent.h \ egldefines.h \ egldisplay.h \ egldriver.h \ @@ -28,6 +29,7 @@ SOURCES = \ eglconfig.c \ eglconfigutil.c \ eglcontext.c \ + eglcurrent.c \ egldisplay.c \ egldriver.c \ eglglobals.c \ diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 9df938e..ea4d6e1 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -321,7 +321,8 @@ eglGetError(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint e = t->LastError; - t->LastError = EGL_SUCCESS; + if (!_eglDummyCurrentThread()) + t->LastError = EGL_SUCCESS; return e; } @@ -546,6 +547,9 @@ eglBindAPI(EGLenum api) { _EGLThreadInfo *t = _eglGetCurrentThread(); + if (_eglDummyCurrentThread()) + return _eglError(EGL_BAD_ALLOC, "eglBindAPI"); + switch (api) { #ifdef EGL_VERSION_1_4 case EGL_OPENGL_API: @@ -603,15 +607,19 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLBoolean eglReleaseThread(void) { - _EGLThreadInfo *t = _eglGetCurrentThread(); - EGLDisplay dpy = eglGetCurrentDisplay(); + EGLDisplay dpy; + + if (_eglDummyCurrentThread()) + return EGL_TRUE; + + dpy = eglGetCurrentDisplay(); if (dpy) { _EGLDriver *drv = _eglLookupDriver(dpy); /* unbind context */ (void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } - _eglDeleteThreadData(t); + _eglPutCurrentThread(); return EGL_TRUE; } diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index 461679d..1ffad4a 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -109,17 +109,6 @@ _eglLookupContext(EGLContext ctx) /** - * Return the currently bound _EGLContext object, or NULL. - */ -_EGLContext * -_eglGetCurrentContext(void) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentContext; -} - - -/** * Just a placeholder/demo function. Real driver will never use this! */ EGLContext @@ -219,6 +208,9 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW); _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ); + if (_eglDummyCurrentThread()) + return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); + /* error checking */ if (ctx) { if (draw == NULL || read == NULL) { diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index 34fee9c..5c84031 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -47,10 +47,6 @@ extern _EGLContext * _eglLookupContext(EGLContext ctx); -extern _EGLContext * -_eglGetCurrentContext(void); - - extern EGLContext _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c new file mode 100644 index 0000000..7b999ab --- /dev/null +++ b/src/egl/main/eglcurrent.c @@ -0,0 +1,261 @@ +#include <stdlib.h> +#include "eglcurrent.h" +#include "eglcontext.h" +#include "egllog.h" + + +static _EGLThreadInfo dummy_thread; + + +#ifdef GLX_USE_TLS +static __thread const _EGLThreadInfo *_egl_TSD; + __attribute__ ((tls_model("initial-exec"))); + +static inline EGLBoolean _eglInitTSD(void) { return EGL_TRUE; } +static inline void _eglFiniTSD(void) { } +static inline void _eglSetTSD(const _EGLThreadInfo *t) { _egl_TSD = t; } + +static inline _EGLThreadInfo *_eglGetTSD(void) +{ + return (_EGLThreadInfo *) _egl_TSD; +} + +#elif PTHREADS +#include <pthread.h> + +static pthread_key_t _egl_TSD; + +static inline EGLBoolean _eglInitTSD(void) +{ + return (pthread_key_create(&_egl_TSD, NULL) == 0); +} + +static inline void _eglFiniTSD(void) +{ + pthread_key_delete(_egl_TSD); +} + +static inline void _eglSetTSD(const _EGLThreadInfo *t) +{ + pthread_setspecific(_egl_TSD, (const void *) t); +} + +static inline _EGLThreadInfo *_eglGetTSD(void) +{ + return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD); +} + +#else /* PTHREADS */ +static const _EGLThreadInfo *_egl_TSD; + +static inline EGLBoolean _eglInitTSD(void) { return EGL_TRUE; } +static inline void _eglFiniTSD(void) { } +static inline void _eglSetTSD(const _EGLThreadInfo *t) { _egl_TSD = t; } + +static inline _EGLThreadInfo *_eglGetTSD(void) +{ + return (_EGLThreadInfo *) _egl_TSD; +} +#endif /* !PTHREADS */ + + +static void +_eglInitThreadInfo(_EGLThreadInfo *t) +{ + t->CurrentContext = NULL; + t->LastError = EGL_SUCCESS; + t->CurrentAPI = EGL_OPENGL_ES_API; /* default, per EGL spec */ +} + + +/** + * Allocate and init a new _EGLThreadInfo object. + */ +static _EGLThreadInfo * +_eglCreateThreadInfo(void) +{ + _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo)); + if (t) + _eglInitThreadInfo(t); + else + t = &dummy_thread; + return t; +} + + +/** + * Delete/free a _EGLThreadInfo object. + */ +static void +_eglDestroyThreadInfo(_EGLThreadInfo *t) +{ + if (t != &dummy_thread) + free(t); +} + + +/** + * Initialize "current thread" management. + */ +EGLBoolean +_eglInitCurrent(void) +{ + _eglInitThreadInfo(&dummy_thread); + return _eglInitTSD(); +} + + +void +_eglFiniCurrent(void) +{ + /* TODO trace and release all threads... */ + _eglFiniTSD(); +} + + +/** + * Return pointer to calling thread's _EGLThreadInfo object. + * Create a new one if needed. + * Never return NULL. + */ +_EGLThreadInfo * +_eglGetCurrentThread(void) +{ + _EGLThreadInfo *t = _eglGetTSD(); + if (!t) { + t = _eglCreateThreadInfo(); + _eglSetTSD(t); + } + + return t; +} + + +void +_eglPutCurrentThread(void) +{ + _EGLThreadInfo *t = _eglGetTSD(); + if (t) { + _eglDestroyThreadInfo(t); + _eglSetTSD(NULL); + } +} + + +/** + * Return if current thread info is dummy. + * A dummy thread info should not be modified. + */ +EGLBoolean +_eglDummyCurrentThread(void) +{ + _EGLThreadInfo *t = _eglGetTSD(); + return (!t || t == &dummy_thread); +} + + +/** + * Return the currently bound _EGLContext object, or NULL. + */ +_EGLContext * +_eglGetCurrentContext(void) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + return t->CurrentContext; +} + + +_EGLDisplay * +_eglGetCurrentDisplay(void) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + _EGLContext *ctx = t->CurrentContext; + if (ctx) + return ctx->Display; + else + return NULL; +} + + +_EGLSurface * +_eglGetCurrentSurface(EGLint readdraw) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + _EGLContext *ctx = t->CurrentContext; + if (ctx) { + switch (readdraw) { + case EGL_DRAW: + return ctx->DrawSurface; + case EGL_READ: + return ctx->ReadSurface; + default: + return NULL; + } + } + return NULL; +} + + +/** + * Record EGL error code. + */ +EGLBoolean +_eglError(EGLint errCode, const char *msg) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + const char *s; + + if (t->LastError == EGL_SUCCESS) { + t->LastError = errCode; + + switch (errCode) { + case EGL_BAD_ACCESS: + s = "EGL_BAD_ACCESS"; + break; + case EGL_BAD_ALLOC: + s = "EGL_BAD_ALLOC"; + break; + case EGL_BAD_ATTRIBUTE: + s = "EGL_BAD_ATTRIBUTE"; + break; + case EGL_BAD_CONFIG: + s = "EGL_BAD_CONFIG"; + break; + case EGL_BAD_CONTEXT: + s = "EGL_BAD_CONTEXT"; + break; + case EGL_BAD_CURRENT_SURFACE: + s = "EGL_BAD_CURRENT_SURFACE"; + break; + case EGL_BAD_DISPLAY: + s = "EGL_BAD_DISPLAY"; + break; + case EGL_BAD_MATCH: + s = "EGL_BAD_MATCH"; + break; + case EGL_BAD_NATIVE_PIXMAP: + s = "EGL_BAD_NATIVE_PIXMAP"; + break; + case EGL_BAD_NATIVE_WINDOW: + s = "EGL_BAD_NATIVE_WINDOW"; + break; + case EGL_BAD_PARAMETER: + s = "EGL_BAD_PARAMETER"; + break; + case EGL_BAD_SURFACE: + s = "EGL_BAD_SURFACE"; + break; + case EGL_BAD_SCREEN_MESA: + s = "EGL_BAD_SCREEN_MESA"; + break; + case EGL_BAD_MODE_MESA: + s = "EGL_BAD_MODE_MESA"; + break; + default: + s = "other"; + } + _eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg); + } + + return EGL_FALSE; +} diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h new file mode 100644 index 0000000..14d2923 --- /dev/null +++ b/src/egl/main/eglcurrent.h @@ -0,0 +1,55 @@ +#ifndef EGLCURRENT_INCLUDED +#define EGLCURRENT_INCLUDED + +#include "egltypedefs.h" +#include "eglhash.h" + + +/** + * Per-thread info + */ +struct _egl_thread_info +{ + EGLint LastError; + _EGLContext *CurrentContext; + EGLenum CurrentAPI; +}; + + +extern EGLBoolean +_eglInitCurrent(void); + + +extern void +_eglFiniCurrent(void); + + +extern _EGLThreadInfo * +_eglGetCurrentThread(void); + + +extern void +_eglPutCurrentThread(void); + + +extern EGLBoolean +_eglDummyCurrentThread(void); + + +extern _EGLContext * +_eglGetCurrentContext(void); + + +extern _EGLDisplay * +_eglGetCurrentDisplay(void); + + +extern _EGLSurface * +_eglGetCurrentSurface(EGLint readdraw); + + +extern EGLBoolean +_eglError(EGLint errCode, const char *msg); + + +#endif /* EGLCURRENT_INCLUDED */ diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 47a2323..01f67f6 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -86,17 +86,6 @@ _eglSaveDisplay(_EGLDisplay *dpy) } -_EGLDisplay * -_eglGetCurrentDisplay(void) -{ - _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) - return ctx->Display; - else - return NULL; -} - - /** * Free all the data hanging of an _EGLDisplay object, but not * the object itself. diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index ff623ee..69f0d13 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -45,10 +45,6 @@ extern void _eglSaveDisplay(_EGLDisplay *dpy); -extern _EGLDisplay * -_eglGetCurrentDisplay(void); - - extern void _eglCleanupDisplay(_EGLDisplay *disp); diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index b770e55..55de394 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -1,6 +1,6 @@ -#include <stdio.h> #include <stdlib.h> #include "eglglobals.h" +#include "egllog.h" struct _egl_global _eglGlobal = { @@ -22,8 +22,8 @@ _eglInitGlobals(void) _eglGlobal.ClientAPIsMask = 0x0; - /* XXX temporary */ - _eglGlobal.ThreadInfo = _eglNewThreadInfo(); + if (!_eglInitCurrent()) + _eglLog(_EGL_FATAL, "failed to initialize \"current\" system"); } } @@ -34,113 +34,8 @@ _eglInitGlobals(void) void _eglDestroyGlobals(void) { + _eglFiniCurrent(); /* XXX TODO walk over table entries, deleting each */ _eglDeleteHashTable(_eglGlobal.Displays); _eglDeleteHashTable(_eglGlobal.Surfaces); } - - -/** - * Allocate and init a new _EGLThreadInfo object. - */ -_EGLThreadInfo * -_eglNewThreadInfo(void) -{ - _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo)); - if (t) { - t->CurrentContext = EGL_NO_CONTEXT; - t->LastError = EGL_SUCCESS; - t->CurrentAPI = EGL_OPENGL_ES_API; /* default, per EGL spec */ - } - return t; -} - - -/** - * Delete/free a _EGLThreadInfo object. - */ -void -_eglDeleteThreadData(_EGLThreadInfo *t) -{ - free(t); -} - - - -/** - * Return pointer to calling thread's _EGLThreadInfo object. - * Create a new one if needed. - * Should never return NULL. - */ -_EGLThreadInfo * -_eglGetCurrentThread(void) -{ - _eglInitGlobals(); - - /* XXX temporary */ - return _eglGlobal.ThreadInfo; -} - - -/** - * Record EGL error code. - */ -void -_eglError(EGLint errCode, const char *msg) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - const char *s; - - if (t->LastError == EGL_SUCCESS) { - t->LastError = errCode; - - switch (errCode) { - case EGL_BAD_ACCESS: - s = "EGL_BAD_ACCESS"; - break; - case EGL_BAD_ALLOC: - s = "EGL_BAD_ALLOC"; - break; - case EGL_BAD_ATTRIBUTE: - s = "EGL_BAD_ATTRIBUTE"; - break; - case EGL_BAD_CONFIG: - s = "EGL_BAD_CONFIG"; - break; - case EGL_BAD_CONTEXT: - s = "EGL_BAD_CONTEXT"; - break; - case EGL_BAD_CURRENT_SURFACE: - s = "EGL_BAD_CURRENT_SURFACE"; - break; - case EGL_BAD_DISPLAY: - s = "EGL_BAD_DISPLAY"; - break; - case EGL_BAD_MATCH: - s = "EGL_BAD_MATCH"; - break; - case EGL_BAD_NATIVE_PIXMAP: - s = "EGL_BAD_NATIVE_PIXMAP"; - break; - case EGL_BAD_NATIVE_WINDOW: - s = "EGL_BAD_NATIVE_WINDOW"; - break; - case EGL_BAD_PARAMETER: - s = "EGL_BAD_PARAMETER"; - break; - case EGL_BAD_SURFACE: - s = "EGL_BAD_SURFACE"; - break; - case EGL_BAD_SCREEN_MESA: - s = "EGL_BAD_SCREEN_MESA"; - break; - case EGL_BAD_MODE_MESA: - s = "EGL_BAD_MODE_MESA"; - break; - default: - s = "other"; - } - /* XXX temporary */ - fprintf(stderr, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg); - } -} diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index 14d8ea4..7384774 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -3,17 +3,7 @@ #include "egltypedefs.h" #include "eglhash.h" - - -/** - * Per-thread info - */ -struct _egl_thread_info -{ - EGLint LastError; - _EGLContext *CurrentContext; - EGLenum CurrentAPI; -}; +#include "eglcurrent.h" /** @@ -33,9 +23,6 @@ struct _egl_global char ClientAPIs[1000]; /**< updated by eglQueryString */ - /* XXX temporary - should be thread-specific data (TSD) */ - _EGLThreadInfo *ThreadInfo; - EGLint NumDrivers; _EGLDriver *Drivers[10]; }; @@ -48,24 +35,8 @@ extern void _eglInitGlobals(void); -extern void +void _eglDestroyGlobals(void); -extern _EGLThreadInfo * -_eglNewThreadInfo(void); - - -extern void -_eglDeleteThreadData(_EGLThreadInfo *t); - - -extern _EGLThreadInfo * -_eglGetCurrentThread(void); - - -extern void -_eglError(EGLint errCode, const char *msg); - - #endif /* EGLGLOBALS_INCLUDED */ diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index 6905aca..964288a 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -259,24 +259,6 @@ _eglLookupSurface(EGLSurface surf) } -_EGLSurface * -_eglGetCurrentSurface(EGLint readdraw) -{ - _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) { - switch (readdraw) { - case EGL_DRAW: - return ctx->DrawSurface; - case EGL_READ: - return ctx->ReadSurface; - default: - return NULL; - } - } - return NULL; -} - - EGLBoolean _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) { diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index 50f965b..3b54221 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -60,10 +60,6 @@ extern _EGLSurface * _eglLookupSurface(EGLSurface surf); -extern _EGLSurface * -_eglGetCurrentSurface(EGLint readdraw); - - extern EGLBoolean _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw); -- 1.6.2.4 ------------------------------------------------------------------------------ Enter the BlackBerry Developer Challenge This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge _______________________________________________ Mesa3d-dev mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mesa3d-dev
