egl: commit missing eglcurrent.[ch] files
authorBrian Paul <brianp@vmware.com>
Fri, 17 Jul 2009 19:36:06 +0000 (13:36 -0600)
committerBrian Paul <brianp@vmware.com>
Fri, 17 Jul 2009 19:36:58 +0000 (13:36 -0600)
Not sure how these got left out from earlier commit.

src/egl/main/eglcurrent.c [new file with mode: 0644]
src/egl/main/eglcurrent.h [new file with mode: 0644]

diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c
new file mode 100644 (file)
index 0000000..96152db
--- /dev/null
@@ -0,0 +1,283 @@
+#include <stdlib.h>
+#include <string.h>
+#include "eglcurrent.h"
+#include "eglcontext.h"
+#include "egllog.h"
+
+
+/* a fallback thread info to guarantee that every thread always has one */
+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)
+{
+   memset(t, 0, sizeof(*t));
+   t->LastError = EGL_SUCCESS;
+   /* default, per EGL spec */
+   t->CurrentAPIIndex = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
+}
+
+
+/**
+ * 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();
+}
+
+
+/**
+ * Finish "current thread" management.
+ */
+void
+_eglFiniCurrent(void)
+{
+   /* TODO trace and release all threads... */
+   _eglFiniTSD();
+}
+
+
+/**
+ * Return the calling thread's thread info.
+ * If the calling thread nevers calls this function before, or if its thread
+ * info was destroyed, a new one is created.  This function never returns NULL.
+ * In the case allocation fails, a dummy one is returned.  See also
+ * _eglIsCurrentThreadDummy.
+ */
+_EGLThreadInfo *
+_eglGetCurrentThread(void)
+{
+   _EGLThreadInfo *t = _eglGetTSD();
+   if (!t) {
+      t = _eglCreateThreadInfo();
+      _eglSetTSD(t);
+   }
+
+   return t;
+}
+
+
+/**
+ * Destroy the calling thread's thread info.
+ */
+void
+_eglDestroyCurrentThread(void)
+{
+   _EGLThreadInfo *t = _eglGetTSD();
+   if (t) {
+      _eglDestroyThreadInfo(t);
+      _eglSetTSD(NULL);
+   }
+}
+
+
+/**
+ * Return true if the calling thread's thread info is dummy.
+ * A dummy thread info is shared by all threads and should not be modified.
+ * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness
+ * before updating the thread info.
+ */
+EGLBoolean
+_eglIsCurrentThreadDummy(void)
+{
+   _EGLThreadInfo *t = _eglGetTSD();
+   return (!t || t == &dummy_thread);
+}
+
+
+/**
+ * Return the currently bound context, or NULL.
+ */
+_EGLContext *
+_eglGetCurrentContext(void)
+{
+   _EGLThreadInfo *t = _eglGetCurrentThread();
+   return t->CurrentContexts[t->CurrentAPIIndex];
+}
+
+
+/**
+ * Return the display of the currently bound context, or NULL.
+ */
+_EGLDisplay *
+_eglGetCurrentDisplay(void)
+{
+   _EGLThreadInfo *t = _eglGetCurrentThread();
+   _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex];
+   if (ctx)
+      return ctx->Display;
+   else
+      return NULL;
+}
+
+
+/**
+ * Return the read or write surface of the currently bound context, or NULL.
+ */
+_EGLSurface *
+_eglGetCurrentSurface(EGLint readdraw)
+{
+   _EGLThreadInfo *t = _eglGetCurrentThread();
+   _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex];
+   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 == &dummy_thread)
+      return EGL_FALSE;
+
+   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 (file)
index 0000000..f9fdf7b
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef EGLCURRENT_INCLUDED
+#define EGLCURRENT_INCLUDED
+
+#include "egltypedefs.h"
+
+
+#define _EGL_API_NUM_INDICES \
+   (EGL_OPENGL_API - EGL_OPENGL_ES_API + 2) /* idx 0 is for EGL_NONE */
+
+
+/**
+ * Per-thread info
+ */
+struct _egl_thread_info
+{
+   EGLint LastError;
+   _EGLContext *CurrentContexts[_EGL_API_NUM_INDICES];
+   /* use index for fast access to current context */
+   EGLint CurrentAPIIndex;
+};
+
+
+extern EGLBoolean
+_eglInitCurrent(void);
+
+
+extern void
+_eglFiniCurrent(void);
+
+
+/**
+ * Return true if a client API enum can be converted to an index.
+ */
+static INLINE EGLBoolean
+_eglIsApiValid(EGLenum api)
+{
+   return ((api >= EGL_OPENGL_ES_API && api <= EGL_OPENGL_API) ||
+           api == EGL_NONE);
+}
+
+
+/**
+ * Convert a client API enum to an index, for use by thread info.
+ * The client API enum is assumed to be valid.
+ */
+static INLINE EGLint
+_eglConvertApiToIndex(EGLenum api)
+{
+   return (api != EGL_NONE) ? api - EGL_OPENGL_ES_API + 1 : 0;
+}
+
+
+/**
+ * Convert an index, used by thread info, to a client API enum.
+ * The index is assumed to be valid.
+ */
+static INLINE EGLenum
+_eglConvertApiFromIndex(EGLint idx)
+{
+   return (idx) ? EGL_OPENGL_ES_API + idx - 1 : EGL_NONE;
+}
+
+
+extern _EGLThreadInfo *
+_eglGetCurrentThread(void);
+
+
+extern void
+_eglDestroyCurrentThread(void);
+
+
+extern EGLBoolean
+_eglIsCurrentThreadDummy(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 */