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

Reply via email to