egl: Use _eglPreloadDrivers.
[mesa.git] / src / egl / main / egldisplay.c
index 7f2d035c66a59999e21197359523f1bca1baa9bf..a65ac6e969c49cee6a333bf7ba6648b0adea0e9f 100644 (file)
 #include "egldisplay.h"
 #include "egldriver.h"
 #include "eglglobals.h"
-#include "eglhash.h"
 #include "eglstring.h"
 #include "eglmutex.h"
 #include "egllog.h"
 
 
-static _EGL_DECLARE_MUTEX(_eglDisplayInitMutex);
-static _EGLHashtable *_eglDisplayHash;
-
-
 /**
  * Finish display management.
  */
-static void
+void
 _eglFiniDisplay(void)
 {
-   _eglLockMutex(&_eglDisplayInitMutex);
-   if (_eglDisplayHash) {
-      EGLuint key = _eglHashFirstEntry(_eglDisplayHash);
+   _EGLDisplay *dpyList, *dpy;
 
-      while (key) {
-         _EGLDisplay *dpy = (_EGLDisplay *)
-            _eglHashLookup(_eglDisplayHash, key);
-         assert(dpy);
+   /* atexit function is called with global mutex locked */
+   dpyList = _eglGlobal.DisplayList;
+   while (dpyList) {
+      /* pop list head */
+      dpy = dpyList;
+      dpyList = dpyList->Next;
 
-         if (dpy->ContextList || dpy->SurfaceList)
-            _eglLog(_EGL_DEBUG, "Display %u is destroyed with resources", key);
+      if (dpy->ContextList || dpy->SurfaceList)
+         _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
 
-         free(dpy);
-
-         key = _eglHashNextEntry(_eglDisplayHash, key);
-      }
-
-      _eglDeleteHashTable(_eglDisplayHash);
-      _eglDisplayHash = NULL;
+      free(dpy);
    }
-   _eglUnlockMutex(&_eglDisplayInitMutex);
+   _eglGlobal.DisplayList = NULL;
 }
 
 
-/* This can be avoided if hash table can be statically initialized */
-static INLINE void
-_eglInitDisplay(void)
+/**
+ * If the first character is '!' we interpret it as specific driver name
+ * (i.e. "!r200" or "!i830").  Whatever follows ':' is interpreted as
+ * arguments.
+ *
+ * The caller may free() the returned driver name.
+ */
+char *
+_eglSplitDisplayString(const char *dpyString, const char **args)
 {
-   if (!_eglDisplayHash) {
-      _eglLockMutex(&_eglDisplayInitMutex);
-
-      /* check again after acquiring lock */
-      if (!_eglDisplayHash) {
-         _eglDisplayHash = _eglNewHashTable();
-
-         _eglAddAtExitCall(_eglFiniDisplay);
-      }
-
-      _eglUnlockMutex(&_eglDisplayInitMutex);
+   char *drv, *p;
+
+   if (!dpyString || dpyString[0] != '!')
+      return NULL;
+   drv = _eglstrdup(dpyString + 1);
+   if (!drv)
+      return NULL;
+
+   p = strchr(dpyString, ':');
+   if (p) {
+      drv[p - dpyString] = '\0';
+      p++;
    }
+   if (args)
+      *args = p;
+
+   return drv;
 }
 
 
@@ -81,15 +81,6 @@ _eglNewDisplay(NativeDisplayType nativeDisplay)
    _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
    if (dpy) {
       dpy->NativeDisplay = nativeDisplay;
-#if defined(_EGL_PLATFORM_X)
-      dpy->Xdpy = (Display *) nativeDisplay;
-#endif
-
-      dpy->DriverName = _eglPreloadDriver(dpy);
-      if (!dpy->DriverName) {
-         free(dpy);
-         return NULL;
-      }
    }
    return dpy;
 }
@@ -102,17 +93,14 @@ _eglNewDisplay(NativeDisplayType nativeDisplay)
 EGLDisplay
 _eglLinkDisplay(_EGLDisplay *dpy)
 {
-   EGLuint key;
+   _eglLockMutex(_eglGlobal.Mutex);
 
-   _eglInitDisplay();
+   dpy->Next = _eglGlobal.DisplayList;
+   _eglGlobal.DisplayList = dpy;
 
-   key = _eglHashGenKey(_eglDisplayHash);
-   assert(key);
-   /* "link" the display to the hash table */
-   _eglHashInsert(_eglDisplayHash, key, dpy);
-   dpy->Handle = (EGLDisplay) _eglUIntToPointer(key);
+   _eglUnlockMutex(_eglGlobal.Mutex);
 
-   return dpy->Handle;
+   return (EGLDisplay) dpy;
 }
 
 
@@ -123,40 +111,25 @@ _eglLinkDisplay(_EGLDisplay *dpy)
 void
 _eglUnlinkDisplay(_EGLDisplay *dpy)
 {
-   EGLuint key = _eglPointerToUInt((void *) dpy->Handle);
-
-   _eglInitDisplay();
-
-   _eglHashRemove(_eglDisplayHash, key);
-   dpy->Handle = EGL_NO_DISPLAY;
-}
+   _EGLDisplay *prev;
 
+   _eglLockMutex(_eglGlobal.Mutex);
 
-/**
- * Return the handle of a linked display, or EGL_NO_DISPLAY.
- */
-EGLDisplay
-_eglGetDisplayHandle(_EGLDisplay *display)
-{
-   if (display)
-      return display->Handle;
-   else
-      return EGL_NO_DISPLAY;
-}
-
-
-/**
- * Lookup a handle to find the linked display.
- * Return NULL if the handle has no corresponding linked display.
- */
-_EGLDisplay *
-_eglLookupDisplay(EGLDisplay dpy)
-{
-   EGLuint key = _eglPointerToUInt((void *) dpy);
-
-   _eglInitDisplay();
+   prev = _eglGlobal.DisplayList;
+   if (prev != dpy) {
+      while (prev) {
+         if (prev->Next == dpy)
+            break;
+         prev = prev->Next;
+      }
+      assert(prev);
+      prev->Next = dpy->Next;
+   }
+   else {
+      _eglGlobal.DisplayList = dpy->Next;
+   }
 
-   return (_EGLDisplay *) _eglHashLookup(_eglDisplayHash, key);
+   _eglUnlockMutex(_eglGlobal.Mutex);
 }
 
 
@@ -167,22 +140,21 @@ _eglLookupDisplay(EGLDisplay dpy)
 _EGLDisplay *
 _eglFindDisplay(NativeDisplayType nativeDisplay)
 {
-   EGLuint key;
+   _EGLDisplay *dpy;
 
-   _eglInitDisplay();
+   _eglLockMutex(_eglGlobal.Mutex);
 
-   /* Walk the hash table.  Should switch to list if it is a problem. */
-   key = _eglHashFirstEntry(_eglDisplayHash);
-   while (key) {
-      _EGLDisplay *dpy = (_EGLDisplay *)
-            _eglHashLookup(_eglDisplayHash, key);
-      assert(dpy);
-
-      if (dpy->NativeDisplay == nativeDisplay)
+   dpy = _eglGlobal.DisplayList;
+   while (dpy) {
+      if (dpy->NativeDisplay == nativeDisplay) {
+         _eglUnlockMutex(_eglGlobal.Mutex);
          return dpy;
-      key = _eglHashNextEntry(_eglDisplayHash, key);
+      }
+      dpy = dpy->Next;
    }
 
+   _eglUnlockMutex(_eglGlobal.Mutex);
+
    return NULL;
 }
 
@@ -282,28 +254,6 @@ _eglUnlinkContext(_EGLContext *ctx)
 }
 
 
-/**
- * Return the handle of a linked context, or EGL_NO_CONTEXT.
- */
-EGLContext
-_eglGetContextHandle(_EGLContext *ctx)
-{
-   return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT);
-}
-
-
-/**
- * Lookup a handle to find the linked context.
- * Return NULL if the handle has no corresponding linked context.
- */
-_EGLContext *
-_eglLookupContext(EGLContext ctx, _EGLDisplay *dpy)
-{
-   _EGLContext *context = (_EGLContext *) ctx;
-   return (context && context->Display) ? context : NULL;
-}
-
-
 /**
  * Link a surface to a display and return the handle of the link.
  * The handle can be passed to client directly.
@@ -347,23 +297,69 @@ _eglUnlinkSurface(_EGLSurface *surf)
 }
 
 
+#ifndef _EGL_SKIP_HANDLE_CHECK
+
+
 /**
- * Return the handle of a linked surface, or EGL_NO_SURFACE.
+ * Return EGL_TRUE if the given handle is a valid handle to a display.
  */
-EGLSurface
-_eglGetSurfaceHandle(_EGLSurface *surf)
+EGLBoolean
+_eglCheckDisplayHandle(EGLDisplay dpy)
 {
-   return (EGLSurface) ((surf && surf->Display) ? surf : EGL_NO_SURFACE);
+   _EGLDisplay *cur;
+
+   _eglLockMutex(_eglGlobal.Mutex);
+   cur = _eglGlobal.DisplayList;
+   while (cur) {
+      if (cur == (_EGLDisplay *) dpy)
+         break;
+      cur = cur->Next;
+   }
+   _eglUnlockMutex(_eglGlobal.Mutex);
+   return (cur != NULL);
 }
 
 
 /**
- * Lookup a handle to find the linked surface.
- * Return NULL if the handle has no corresponding linked surface.
+ * Return EGL_TRUE if the given handle is a valid handle to a context.
  */
-_EGLSurface *
-_eglLookupSurface(EGLSurface surface, _EGLDisplay *dpy)
+EGLBoolean
+_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy)
 {
-   _EGLSurface *surf = (_EGLSurface *) surface;
-   return (surf && surf->Display) ? surf : NULL;
+   _EGLContext *cur = NULL;
+
+   if (dpy)
+      cur = dpy->ContextList;
+   while (cur) {
+      if (cur == (_EGLContext *) ctx) {
+         assert(cur->Display == dpy);
+         break;
+      }
+      cur = cur->Next;
+   }
+   return (cur != NULL);
 }
+
+
+/**
+ * Return EGL_TRUE if the given handle is a valid handle to a surface.
+ */
+EGLBoolean
+_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy)
+{
+   _EGLSurface *cur = NULL;
+
+   if (dpy)
+      cur = dpy->SurfaceList;
+   while (cur) {
+      if (cur == (_EGLSurface *) surf) {
+         assert(cur->Display == dpy);
+         break;
+      }
+      cur = cur->Next;
+   }
+   return (cur != NULL);
+}
+
+
+#endif /* !_EGL_SKIP_HANDLE_CHECK */