egldisplay.c revision 3464ebd5
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 5 * Copyright 2010-2011 LunarG, Inc. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30 31/** 32 * Functions related to EGLDisplay. 33 */ 34 35#include <assert.h> 36#include <stdlib.h> 37#include <string.h> 38#include "eglcontext.h" 39#include "eglsurface.h" 40#include "egldisplay.h" 41#include "egldriver.h" 42#include "eglglobals.h" 43#include "eglmutex.h" 44#include "egllog.h" 45 46 47/** 48 * Return the native platform by parsing EGL_PLATFORM. 49 */ 50static _EGLPlatformType 51_eglGetNativePlatformFromEnv(void) 52{ 53 /* map --with-egl-platforms names to platform types */ 54 static const struct { 55 _EGLPlatformType platform; 56 const char *name; 57 } egl_platforms[_EGL_NUM_PLATFORMS] = { 58 { _EGL_PLATFORM_WINDOWS, "gdi" }, 59 { _EGL_PLATFORM_X11, "x11" }, 60 { _EGL_PLATFORM_WAYLAND, "wayland" }, 61 { _EGL_PLATFORM_DRM, "drm" }, 62 { _EGL_PLATFORM_FBDEV, "fbdev" } 63 }; 64 _EGLPlatformType plat = _EGL_INVALID_PLATFORM; 65 const char *plat_name; 66 EGLint i; 67 68 plat_name = getenv("EGL_PLATFORM"); 69 /* try deprecated env variable */ 70 if (!plat_name || !plat_name[0]) 71 plat_name = getenv("EGL_DISPLAY"); 72 if (!plat_name || !plat_name[0]) 73 return _EGL_INVALID_PLATFORM; 74 75 for (i = 0; i < _EGL_NUM_PLATFORMS; i++) { 76 if (strcmp(egl_platforms[i].name, plat_name) == 0) { 77 plat = egl_platforms[i].platform; 78 break; 79 } 80 } 81 82 return plat; 83} 84 85 86/** 87 * Return the native platform. It is the platform of the EGL native types. 88 */ 89_EGLPlatformType 90_eglGetNativePlatform(void) 91{ 92 static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM; 93 94 if (native_platform == _EGL_INVALID_PLATFORM) { 95 native_platform = _eglGetNativePlatformFromEnv(); 96 if (native_platform == _EGL_INVALID_PLATFORM) 97 native_platform = _EGL_NATIVE_PLATFORM; 98 } 99 100 return native_platform; 101} 102 103 104/** 105 * Finish display management. 106 */ 107void 108_eglFiniDisplay(void) 109{ 110 _EGLDisplay *dpyList, *dpy; 111 112 /* atexit function is called with global mutex locked */ 113 dpyList = _eglGlobal.DisplayList; 114 while (dpyList) { 115 EGLint i; 116 117 /* pop list head */ 118 dpy = dpyList; 119 dpyList = dpyList->Next; 120 121 for (i = 0; i < _EGL_NUM_RESOURCES; i++) { 122 if (dpy->ResourceLists[i]) { 123 _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy); 124 break; 125 } 126 } 127 128 free(dpy); 129 } 130 _eglGlobal.DisplayList = NULL; 131} 132 133 134/** 135 * Find the display corresponding to the specified native display, or create a 136 * new one. 137 */ 138_EGLDisplay * 139_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy) 140{ 141 _EGLDisplay *dpy; 142 143 if (plat == _EGL_INVALID_PLATFORM) 144 return NULL; 145 146 _eglLockMutex(_eglGlobal.Mutex); 147 148 /* search the display list first */ 149 dpy = _eglGlobal.DisplayList; 150 while (dpy) { 151 if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy) 152 break; 153 dpy = dpy->Next; 154 } 155 156 /* create a new display */ 157 if (!dpy) { 158 dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay)); 159 if (dpy) { 160 _eglInitMutex(&dpy->Mutex); 161 dpy->Platform = plat; 162 dpy->PlatformDisplay = plat_dpy; 163 164 /* add to the display list */ 165 dpy->Next = _eglGlobal.DisplayList; 166 _eglGlobal.DisplayList = dpy; 167 } 168 } 169 170 _eglUnlockMutex(_eglGlobal.Mutex); 171 172 return dpy; 173} 174 175 176/** 177 * Destroy the contexts and surfaces that are linked to the display. 178 */ 179void 180_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display) 181{ 182 _EGLResource *list; 183 184 list = display->ResourceLists[_EGL_RESOURCE_CONTEXT]; 185 while (list) { 186 _EGLContext *ctx = (_EGLContext *) list; 187 list = list->Next; 188 189 _eglUnlinkContext(ctx); 190 drv->API.DestroyContext(drv, display, ctx); 191 } 192 assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]); 193 194 list = display->ResourceLists[_EGL_RESOURCE_SURFACE]; 195 while (list) { 196 _EGLSurface *surf = (_EGLSurface *) list; 197 list = list->Next; 198 199 _eglUnlinkSurface(surf); 200 drv->API.DestroySurface(drv, display, surf); 201 } 202 assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]); 203} 204 205 206/** 207 * Free all the data hanging of an _EGLDisplay object, but not 208 * the object itself. 209 */ 210void 211_eglCleanupDisplay(_EGLDisplay *disp) 212{ 213 if (disp->Configs) { 214 _eglDestroyArray(disp->Configs, free); 215 disp->Configs = NULL; 216 } 217 218 /* XXX incomplete */ 219} 220 221 222/** 223 * Return EGL_TRUE if the given handle is a valid handle to a display. 224 */ 225EGLBoolean 226_eglCheckDisplayHandle(EGLDisplay dpy) 227{ 228 _EGLDisplay *cur; 229 230 _eglLockMutex(_eglGlobal.Mutex); 231 cur = _eglGlobal.DisplayList; 232 while (cur) { 233 if (cur == (_EGLDisplay *) dpy) 234 break; 235 cur = cur->Next; 236 } 237 _eglUnlockMutex(_eglGlobal.Mutex); 238 return (cur != NULL); 239} 240 241 242/** 243 * Return EGL_TRUE if the given resource is valid. That is, the display does 244 * own the resource. 245 */ 246EGLBoolean 247_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy) 248{ 249 _EGLResource *list = dpy->ResourceLists[type]; 250 251 if (!res) 252 return EGL_FALSE; 253 254 while (list) { 255 if (res == (void *) list) { 256 assert(list->Display == dpy); 257 break; 258 } 259 list = list->Next; 260 } 261 262 return (list != NULL); 263} 264 265 266/** 267 * Initialize a display resource. 268 */ 269void 270_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *dpy) 271{ 272 memset(res, 0, size); 273 res->Display = dpy; 274 res->RefCount = 1; 275} 276 277 278/** 279 * Increment reference count for the resource. 280 */ 281void 282_eglGetResource(_EGLResource *res) 283{ 284 assert(res && res->RefCount > 0); 285 /* hopefully a resource is always manipulated with its display locked */ 286 res->RefCount++; 287} 288 289 290/** 291 * Decrement reference count for the resource. 292 */ 293EGLBoolean 294_eglPutResource(_EGLResource *res) 295{ 296 assert(res && res->RefCount > 0); 297 res->RefCount--; 298 return (!res->RefCount); 299} 300 301 302/** 303 * Link a resource to its display. 304 */ 305void 306_eglLinkResource(_EGLResource *res, _EGLResourceType type) 307{ 308 assert(res->Display); 309 310 res->IsLinked = EGL_TRUE; 311 res->Next = res->Display->ResourceLists[type]; 312 res->Display->ResourceLists[type] = res; 313 _eglGetResource(res); 314} 315 316 317/** 318 * Unlink a linked resource from its display. 319 */ 320void 321_eglUnlinkResource(_EGLResource *res, _EGLResourceType type) 322{ 323 _EGLResource *prev; 324 325 prev = res->Display->ResourceLists[type]; 326 if (prev != res) { 327 while (prev) { 328 if (prev->Next == res) 329 break; 330 prev = prev->Next; 331 } 332 assert(prev); 333 prev->Next = res->Next; 334 } 335 else { 336 res->Display->ResourceLists[type] = res->Next; 337 } 338 339 res->Next = NULL; 340 res->IsLinked = EGL_FALSE; 341 _eglPutResource(res); 342 343 /* We always unlink before destroy. The driver still owns a reference */ 344 assert(res->RefCount); 345} 346