X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fmain%2Fegldisplay.c;h=e14d0c1b63b94b54924cecb3885cfbd26b7d297c;hb=5e66d1893234b3002d71985c05253321d4cdedc4;hp=47a2323eafb3923e508fdb9527dcc64c3983d243;hpb=49680dae5dd014503974f20c0b943244622ca3d5;p=mesa.git diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 47a2323eafb..e14d0c1b63b 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -1,4 +1,3 @@ - /** * Functions related to EGLDisplay. */ @@ -7,11 +6,37 @@ #include #include #include "eglcontext.h" +#include "eglsurface.h" #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" -#include "eglhash.h" #include "eglstring.h" +#include "eglmutex.h" +#include "egllog.h" + + +/** + * Finish display management. + */ +void +_eglFiniDisplay(void) +{ + _EGLDisplay *dpyList, *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 %p is destroyed with resources", dpy); + + free(dpy); + } + _eglGlobal.DisplayList = NULL; +} /** @@ -25,75 +50,114 @@ _eglNewDisplay(NativeDisplayType nativeDisplay) { _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay)); if (dpy) { - EGLuint key = _eglHashGenKey(_eglGlobal.Displays); - - dpy->Handle = (EGLDisplay) key; - _eglHashInsert(_eglGlobal.Displays, key, dpy); - dpy->NativeDisplay = nativeDisplay; -#if defined(_EGL_PLATFORM_X) - dpy->Xdpy = (Display *) nativeDisplay; -#endif - - dpy->DriverName = _eglChooseDriver(dpy); - if (!dpy->DriverName) { - free(dpy); - return NULL; - } } return dpy; } /** - * Return the public handle for an internal _EGLDisplay. - * This is the inverse of _eglLookupDisplay(). + * Link a display to itself and return the handle of the link. + * The handle can be passed to client directly. */ EGLDisplay -_eglGetDisplayHandle(_EGLDisplay *display) +_eglLinkDisplay(_EGLDisplay *dpy) { - if (display) - return display->Handle; - else - return EGL_NO_DISPLAY; + _eglLockMutex(_eglGlobal.Mutex); + + dpy->Next = _eglGlobal.DisplayList; + _eglGlobal.DisplayList = dpy; + + _eglUnlockMutex(_eglGlobal.Mutex); + + return (EGLDisplay) dpy; } - + /** - * Return the _EGLDisplay object that corresponds to the given public/ - * opaque display handle. - * This is the inverse of _eglGetDisplayHandle(). + * Unlink a linked display from itself. + * Accessing an unlinked display should generate EGL_BAD_DISPLAY error. */ -_EGLDisplay * -_eglLookupDisplay(EGLDisplay dpy) +void +_eglUnlinkDisplay(_EGLDisplay *dpy) { - EGLuint key = (EGLuint) dpy; - if (!_eglGlobal.Displays) - return NULL; - return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key); + _EGLDisplay *prev; + + _eglLockMutex(_eglGlobal.Mutex); + + 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; + } + + _eglUnlockMutex(_eglGlobal.Mutex); } -void -_eglSaveDisplay(_EGLDisplay *dpy) +/** + * Find the display corresponding to the specified native display id in all + * linked displays. + */ +_EGLDisplay * +_eglFindDisplay(NativeDisplayType nativeDisplay) { - EGLuint key = _eglHashGenKey(_eglGlobal.Displays); - assert(dpy); - assert(!dpy->Handle); - dpy->Handle = (EGLDisplay) key; - assert(dpy->Handle); - _eglHashInsert(_eglGlobal.Displays, key, dpy); + _EGLDisplay *dpy; + + _eglLockMutex(_eglGlobal.Mutex); + + dpy = _eglGlobal.DisplayList; + while (dpy) { + if (dpy->NativeDisplay == nativeDisplay) { + _eglUnlockMutex(_eglGlobal.Mutex); + return dpy; + } + dpy = dpy->Next; + } + + _eglUnlockMutex(_eglGlobal.Mutex); + + return NULL; } -_EGLDisplay * -_eglGetCurrentDisplay(void) +/** + * Destroy the contexts and surfaces that are linked to the display. + */ +void +_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display) { - _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) - return ctx->Display; - else - return NULL; + _EGLContext *contexts; + _EGLSurface *surfaces; + + contexts = display->ContextList; + surfaces = display->SurfaceList; + + while (contexts) { + _EGLContext *ctx = contexts; + contexts = contexts->Next; + + _eglUnlinkContext(ctx); + drv->API.DestroyContext(drv, display, ctx); + } + assert(!display->ContextList); + + while (surfaces) { + _EGLSurface *surf = surfaces; + surfaces = surfaces->Next; + + _eglUnlinkSurface(surf); + drv->API.DestroySurface(drv, display, surf); + } + assert(!display->SurfaceList); } @@ -106,16 +170,103 @@ _eglCleanupDisplay(_EGLDisplay *disp) { EGLint i; - for (i = 0; i < disp->NumConfigs; i++) { - free(disp->Configs[i]); + if (disp->Configs) { + for (i = 0; i < disp->NumConfigs; i++) + free(disp->Configs[i]); + free(disp->Configs); + disp->Configs = NULL; + disp->NumConfigs = 0; } - free(disp->Configs); - disp->Configs = NULL; /* XXX incomplete */ +} + + +/** + * Link a surface to a display and return the handle of the link. + * The handle can be passed to client directly. + */ +EGLSurface +_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy) +{ + surf->Display = dpy; + surf->Next = dpy->SurfaceList; + dpy->SurfaceList = surf; + return (EGLSurface) surf; +} + + +/** + * Unlink a linked surface from its display. + * Accessing an unlinked surface should generate EGL_BAD_SURFACE error. + */ +void +_eglUnlinkSurface(_EGLSurface *surf) +{ + _EGLSurface *prev; + + prev = surf->Display->SurfaceList; + if (prev != surf) { + while (prev) { + if (prev->Next == surf) + break; + prev = prev->Next; + } + assert(prev); + prev->Next = surf->Next; + } + else { + prev = NULL; + surf->Display->SurfaceList = surf->Next; + } + + surf->Next = NULL; + surf->Display = NULL; +} - free((void *) disp->DriverName); - disp->DriverName = NULL; - /* driver deletes the _EGLDisplay object */ +#ifndef _EGL_SKIP_HANDLE_CHECK + + +/** + * Return EGL_TRUE if the given handle is a valid handle to a display. + */ +EGLBoolean +_eglCheckDisplayHandle(EGLDisplay dpy) +{ + _EGLDisplay *cur; + + _eglLockMutex(_eglGlobal.Mutex); + cur = _eglGlobal.DisplayList; + while (cur) { + if (cur == (_EGLDisplay *) dpy) + break; + cur = cur->Next; + } + _eglUnlockMutex(_eglGlobal.Mutex); + 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 */