diff options
Diffstat (limited to 'src/egl/main/egldisplay.c')
-rw-r--r-- | src/egl/main/egldisplay.c | 114 |
1 files changed, 95 insertions, 19 deletions
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 89de609d0b4..feae1d60409 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -1,4 +1,3 @@ - /** * Functions related to EGLDisplay. */ @@ -13,6 +12,67 @@ #include "eglglobals.h" #include "eglhash.h" #include "eglstring.h" +#include "eglmutex.h" +#include "egllog.h" + + +static _EGL_DECLARE_MUTEX(_eglDisplayInitMutex); +static _EGLHashtable *_eglDisplayHash; +/* TODO surface hash table should be per-display */ +static _EGLHashtable *_eglSurfaceHash; + + +/** + * Finish display management. + */ +static void +_eglFiniDisplay(void) +{ + _eglLockMutex(&_eglDisplayInitMutex); + if (_eglDisplayHash) { + EGLuint key = _eglHashFirstEntry(_eglDisplayHash); + + while (key) { + _EGLDisplay *dpy = (_EGLDisplay *) + _eglHashLookup(_eglDisplayHash, key); + assert(dpy); + + if (dpy->ContextList || dpy->SurfaceList) + _eglLog(_EGL_DEBUG, "Display %u is destroyed with resources", key); + + _eglCleanupDisplay(dpy); + free(dpy); + + key = _eglHashNextEntry(_eglDisplayHash, key); + } + + _eglDeleteHashTable(_eglDisplayHash); + _eglDisplayHash = NULL; + _eglDeleteHashTable(_eglSurfaceHash); + _eglSurfaceHash = NULL; + } + _eglUnlockMutex(&_eglDisplayInitMutex); +} + + +/* This can be avoided if hash table can be statically initialized */ +static INLINE void +_eglInitDisplay(void) +{ + if (!_eglDisplayHash) { + _eglLockMutex(&_eglDisplayInitMutex); + + /* check again after acquiring lock */ + if (!_eglDisplayHash) { + _eglDisplayHash = _eglNewHashTable(); + _eglSurfaceHash = _eglNewHashTable(); + + _eglAddAtExitCall(_eglFiniDisplay); + } + + _eglUnlockMutex(&_eglDisplayInitMutex); + } +} /** @@ -31,6 +91,9 @@ _eglNewDisplay(NativeDisplayType nativeDisplay) dpy->Xdpy = (Display *) nativeDisplay; #endif + _eglInitDisplay(); + dpy->SurfaceHash = _eglSurfaceHash; + dpy->DriverName = _eglChooseDriver(dpy); if (!dpy->DriverName) { free(dpy); @@ -49,11 +112,14 @@ EGLDisplay _eglLinkDisplay(_EGLDisplay *dpy) { EGLuint key; - key = _eglHashGenKey(_eglGlobal.Displays); + + _eglInitDisplay(); + + key = _eglHashGenKey(_eglDisplayHash); assert(key); /* "link" the display to the hash table */ - _eglHashInsert(_eglGlobal.Displays, key, dpy); - dpy->Handle = (EGLDisplay) key; + _eglHashInsert(_eglDisplayHash, key, dpy); + dpy->Handle = (EGLDisplay) _eglUIntToPointer(key); return dpy->Handle; } @@ -66,7 +132,11 @@ _eglLinkDisplay(_EGLDisplay *dpy) void _eglUnlinkDisplay(_EGLDisplay *dpy) { - _eglHashRemove(_eglGlobal.Displays, (EGLuint) dpy->Handle); + EGLuint key = _eglPointerToUInt((void *) dpy->Handle); + + _eglInitDisplay(); + + _eglHashRemove(_eglDisplayHash, key); dpy->Handle = EGL_NO_DISPLAY; } @@ -83,7 +153,7 @@ _eglGetDisplayHandle(_EGLDisplay *display) return EGL_NO_DISPLAY; } - + /** * Lookup a handle to find the linked display. * Return NULL if the handle has no corresponding linked display. @@ -91,8 +161,11 @@ _eglGetDisplayHandle(_EGLDisplay *display) _EGLDisplay * _eglLookupDisplay(EGLDisplay dpy) { - EGLuint key = (EGLuint) dpy; - return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key); + EGLuint key = _eglPointerToUInt((void *) dpy); + + _eglInitDisplay(); + + return (_EGLDisplay *) _eglHashLookup(_eglDisplayHash, key); } @@ -103,17 +176,20 @@ _eglLookupDisplay(EGLDisplay dpy) _EGLDisplay * _eglFindDisplay(NativeDisplayType nativeDisplay) { - EGLuint key = _eglHashFirstEntry(_eglGlobal.Displays); + EGLuint key; + + _eglInitDisplay(); /* Walk the hash table. Should switch to list if it is a problem. */ + key = _eglHashFirstEntry(_eglDisplayHash); while (key) { _EGLDisplay *dpy = (_EGLDisplay *) - _eglHashLookup(_eglGlobal.Displays, key); + _eglHashLookup(_eglDisplayHash, key); assert(dpy); if (dpy->NativeDisplay == nativeDisplay) return dpy; - key = _eglHashNextEntry(_eglGlobal.Displays, key); + key = _eglHashNextEntry(_eglDisplayHash, key); } return NULL; @@ -224,7 +300,7 @@ _eglUnlinkContext(_EGLContext *ctx) EGLContext _eglGetContextHandle(_EGLContext *ctx) { - return (EGLContext) (ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT; + return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT); } @@ -253,11 +329,11 @@ _eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy) surf->Next = dpy->SurfaceList; dpy->SurfaceList = surf; - key = _eglHashGenKey(_eglGlobal.Surfaces); + key = _eglHashGenKey(dpy->SurfaceHash); assert(key); - _eglHashInsert(_eglGlobal.Surfaces, key, surf); + _eglHashInsert(dpy->SurfaceHash, key, surf); - surf->Handle = (EGLSurface) key; + surf->Handle = (EGLSurface) _eglUIntToPointer(key); return surf->Handle; } @@ -270,8 +346,9 @@ void _eglUnlinkSurface(_EGLSurface *surf) { _EGLSurface *prev; + EGLuint key = _eglPointerToUInt((void *) surf->Handle); - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surf->Handle); + _eglHashRemove(surf->Display->SurfaceHash, key); surf->Handle = EGL_NO_SURFACE; prev = surf->Display->SurfaceList; @@ -314,7 +391,6 @@ _eglGetSurfaceHandle(_EGLSurface *surface) _EGLSurface * _eglLookupSurface(EGLSurface surf) { - _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, - (EGLuint) surf); - return c; + EGLuint key = _eglPointerToUInt((void *) surf); + return (_EGLSurface *) _eglHashLookup(_eglSurfaceHash, key); } |