egldisplay.c revision 4a49301e
1/** 2 * Functions related to EGLDisplay. 3 */ 4 5#include <assert.h> 6#include <stdlib.h> 7#include <string.h> 8#include "eglcontext.h" 9#include "eglsurface.h" 10#include "egldisplay.h" 11#include "egldriver.h" 12#include "eglglobals.h" 13#include "eglstring.h" 14#include "eglmutex.h" 15#include "egllog.h" 16 17 18/** 19 * Finish display management. 20 */ 21void 22_eglFiniDisplay(void) 23{ 24 _EGLDisplay *dpyList, *dpy; 25 26 /* atexit function is called with global mutex locked */ 27 dpyList = _eglGlobal.DisplayList; 28 while (dpyList) { 29 /* pop list head */ 30 dpy = dpyList; 31 dpyList = dpyList->Next; 32 33 if (dpy->ContextList || dpy->SurfaceList) 34 _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy); 35 36 free(dpy); 37 } 38 _eglGlobal.DisplayList = NULL; 39} 40 41 42/** 43 * If the first character is '!' we interpret it as specific driver name 44 * (i.e. "!r200" or "!i830"). Whatever follows ':' is interpreted as 45 * arguments. 46 * 47 * The caller may free() the returned driver name. 48 */ 49char * 50_eglSplitDisplayString(const char *dpyString, const char **args) 51{ 52 char *drv, *p; 53 54 if (!dpyString || dpyString[0] != '!') 55 return NULL; 56 drv = _eglstrdup(dpyString + 1); 57 if (!drv) 58 return NULL; 59 60 p = strchr(dpyString, ':'); 61 if (p) { 62 drv[p - dpyString] = '\0'; 63 p++; 64 } 65 if (args) 66 *args = p; 67 68 return drv; 69} 70 71 72/** 73 * Allocate a new _EGLDisplay object for the given nativeDisplay handle. 74 * We'll also try to determine the device driver name at this time. 75 * 76 * Note that nativeDisplay may be an X Display ptr, or a string. 77 */ 78_EGLDisplay * 79_eglNewDisplay(NativeDisplayType nativeDisplay) 80{ 81 _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay)); 82 if (dpy) { 83 dpy->NativeDisplay = nativeDisplay; 84 85 dpy->DriverName = _eglPreloadDriver(dpy); 86 if (!dpy->DriverName) { 87 free(dpy); 88 return NULL; 89 } 90 } 91 return dpy; 92} 93 94 95/** 96 * Link a display to itself and return the handle of the link. 97 * The handle can be passed to client directly. 98 */ 99EGLDisplay 100_eglLinkDisplay(_EGLDisplay *dpy) 101{ 102 _eglLockMutex(_eglGlobal.Mutex); 103 104 dpy->Next = _eglGlobal.DisplayList; 105 _eglGlobal.DisplayList = dpy; 106 107 _eglUnlockMutex(_eglGlobal.Mutex); 108 109 return (EGLDisplay) dpy; 110} 111 112 113/** 114 * Unlink a linked display from itself. 115 * Accessing an unlinked display should generate EGL_BAD_DISPLAY error. 116 */ 117void 118_eglUnlinkDisplay(_EGLDisplay *dpy) 119{ 120 _EGLDisplay *prev; 121 122 _eglLockMutex(_eglGlobal.Mutex); 123 124 prev = _eglGlobal.DisplayList; 125 if (prev != dpy) { 126 while (prev) { 127 if (prev->Next == dpy) 128 break; 129 prev = prev->Next; 130 } 131 assert(prev); 132 prev->Next = dpy->Next; 133 } 134 else { 135 _eglGlobal.DisplayList = dpy->Next; 136 } 137 138 _eglUnlockMutex(_eglGlobal.Mutex); 139} 140 141 142/** 143 * Find the display corresponding to the specified native display id in all 144 * linked displays. 145 */ 146_EGLDisplay * 147_eglFindDisplay(NativeDisplayType nativeDisplay) 148{ 149 _EGLDisplay *dpy; 150 151 _eglLockMutex(_eglGlobal.Mutex); 152 153 dpy = _eglGlobal.DisplayList; 154 while (dpy) { 155 if (dpy->NativeDisplay == nativeDisplay) { 156 _eglUnlockMutex(_eglGlobal.Mutex); 157 return dpy; 158 } 159 dpy = dpy->Next; 160 } 161 162 _eglUnlockMutex(_eglGlobal.Mutex); 163 164 return NULL; 165} 166 167 168/** 169 * Destroy the contexts and surfaces that are linked to the display. 170 */ 171void 172_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display) 173{ 174 _EGLContext *contexts; 175 _EGLSurface *surfaces; 176 177 contexts = display->ContextList; 178 surfaces = display->SurfaceList; 179 180 while (contexts) { 181 _EGLContext *ctx = contexts; 182 contexts = contexts->Next; 183 184 _eglUnlinkContext(ctx); 185 drv->API.DestroyContext(drv, display, ctx); 186 } 187 assert(!display->ContextList); 188 189 while (surfaces) { 190 _EGLSurface *surf = surfaces; 191 surfaces = surfaces->Next; 192 193 _eglUnlinkSurface(surf); 194 drv->API.DestroySurface(drv, display, surf); 195 } 196 assert(!display->SurfaceList); 197} 198 199 200/** 201 * Free all the data hanging of an _EGLDisplay object, but not 202 * the object itself. 203 */ 204void 205_eglCleanupDisplay(_EGLDisplay *disp) 206{ 207 EGLint i; 208 209 if (disp->Configs) { 210 for (i = 0; i < disp->NumConfigs; i++) 211 free(disp->Configs[i]); 212 free(disp->Configs); 213 disp->Configs = NULL; 214 disp->NumConfigs = 0; 215 } 216 217 /* XXX incomplete */ 218} 219 220 221/** 222 * Link a context to a display and return the handle of the link. 223 * The handle can be passed to client directly. 224 */ 225EGLContext 226_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy) 227{ 228 ctx->Display = dpy; 229 ctx->Next = dpy->ContextList; 230 dpy->ContextList = ctx; 231 return (EGLContext) ctx; 232} 233 234 235/** 236 * Unlink a linked context from its display. 237 * Accessing an unlinked context should generate EGL_BAD_CONTEXT error. 238 */ 239void 240_eglUnlinkContext(_EGLContext *ctx) 241{ 242 _EGLContext *prev; 243 244 prev = ctx->Display->ContextList; 245 if (prev != ctx) { 246 while (prev) { 247 if (prev->Next == ctx) 248 break; 249 prev = prev->Next; 250 } 251 assert(prev); 252 prev->Next = ctx->Next; 253 } 254 else { 255 ctx->Display->ContextList = ctx->Next; 256 } 257 258 ctx->Next = NULL; 259 ctx->Display = NULL; 260} 261 262 263/** 264 * Link a surface to a display and return the handle of the link. 265 * The handle can be passed to client directly. 266 */ 267EGLSurface 268_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy) 269{ 270 surf->Display = dpy; 271 surf->Next = dpy->SurfaceList; 272 dpy->SurfaceList = surf; 273 return (EGLSurface) surf; 274} 275 276 277/** 278 * Unlink a linked surface from its display. 279 * Accessing an unlinked surface should generate EGL_BAD_SURFACE error. 280 */ 281void 282_eglUnlinkSurface(_EGLSurface *surf) 283{ 284 _EGLSurface *prev; 285 286 prev = surf->Display->SurfaceList; 287 if (prev != surf) { 288 while (prev) { 289 if (prev->Next == surf) 290 break; 291 prev = prev->Next; 292 } 293 assert(prev); 294 prev->Next = surf->Next; 295 } 296 else { 297 prev = NULL; 298 surf->Display->SurfaceList = surf->Next; 299 } 300 301 surf->Next = NULL; 302 surf->Display = NULL; 303} 304 305 306#ifndef _EGL_SKIP_HANDLE_CHECK 307 308 309/** 310 * Return EGL_TRUE if the given handle is a valid handle to a display. 311 */ 312EGLBoolean 313_eglCheckDisplayHandle(EGLDisplay dpy) 314{ 315 _EGLDisplay *cur; 316 317 _eglLockMutex(_eglGlobal.Mutex); 318 cur = _eglGlobal.DisplayList; 319 while (cur) { 320 if (cur == (_EGLDisplay *) dpy) 321 break; 322 cur = cur->Next; 323 } 324 _eglUnlockMutex(_eglGlobal.Mutex); 325 return (cur != NULL); 326} 327 328 329/** 330 * Return EGL_TRUE if the given handle is a valid handle to a context. 331 */ 332EGLBoolean 333_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy) 334{ 335 _EGLContext *cur = NULL; 336 337 if (dpy) 338 cur = dpy->ContextList; 339 while (cur) { 340 if (cur == (_EGLContext *) ctx) { 341 assert(cur->Display == dpy); 342 break; 343 } 344 cur = cur->Next; 345 } 346 return (cur != NULL); 347} 348 349 350/** 351 * Return EGL_TRUE if the given handle is a valid handle to a surface. 352 */ 353EGLBoolean 354_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy) 355{ 356 _EGLSurface *cur = NULL; 357 358 if (dpy) 359 cur = dpy->SurfaceList; 360 while (cur) { 361 if (cur == (_EGLSurface *) surf) { 362 assert(cur->Display == dpy); 363 break; 364 } 365 cur = cur->Next; 366 } 367 return (cur != NULL); 368} 369 370 371#endif /* !_EGL_SKIP_HANDLE_CHECK */ 372