egldisplay.c revision 3464ebd5
13464ebd5Sriastradh/************************************************************************** 23464ebd5Sriastradh * 33464ebd5Sriastradh * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 43464ebd5Sriastradh * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 53464ebd5Sriastradh * Copyright 2010-2011 LunarG, Inc. 63464ebd5Sriastradh * All Rights Reserved. 73464ebd5Sriastradh * 83464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 93464ebd5Sriastradh * copy of this software and associated documentation files (the 103464ebd5Sriastradh * "Software"), to deal in the Software without restriction, including 113464ebd5Sriastradh * without limitation the rights to use, copy, modify, merge, publish, 123464ebd5Sriastradh * distribute, sub license, and/or sell copies of the Software, and to 133464ebd5Sriastradh * permit persons to whom the Software is furnished to do so, subject to 143464ebd5Sriastradh * the following conditions: 153464ebd5Sriastradh * 163464ebd5Sriastradh * The above copyright notice and this permission notice (including the 173464ebd5Sriastradh * next paragraph) shall be included in all copies or substantial portions 183464ebd5Sriastradh * of the Software. 193464ebd5Sriastradh * 203464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 213464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 223464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 233464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 243464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 253464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 263464ebd5Sriastradh * DEALINGS IN THE SOFTWARE. 273464ebd5Sriastradh * 283464ebd5Sriastradh **************************************************************************/ 293464ebd5Sriastradh 303464ebd5Sriastradh 314a49301eSmrg/** 324a49301eSmrg * Functions related to EGLDisplay. 334a49301eSmrg */ 344a49301eSmrg 354a49301eSmrg#include <assert.h> 364a49301eSmrg#include <stdlib.h> 374a49301eSmrg#include <string.h> 384a49301eSmrg#include "eglcontext.h" 394a49301eSmrg#include "eglsurface.h" 404a49301eSmrg#include "egldisplay.h" 414a49301eSmrg#include "egldriver.h" 424a49301eSmrg#include "eglglobals.h" 434a49301eSmrg#include "eglmutex.h" 444a49301eSmrg#include "egllog.h" 454a49301eSmrg 464a49301eSmrg 473464ebd5Sriastradh/** 483464ebd5Sriastradh * Return the native platform by parsing EGL_PLATFORM. 493464ebd5Sriastradh */ 503464ebd5Sriastradhstatic _EGLPlatformType 513464ebd5Sriastradh_eglGetNativePlatformFromEnv(void) 523464ebd5Sriastradh{ 533464ebd5Sriastradh /* map --with-egl-platforms names to platform types */ 543464ebd5Sriastradh static const struct { 553464ebd5Sriastradh _EGLPlatformType platform; 563464ebd5Sriastradh const char *name; 573464ebd5Sriastradh } egl_platforms[_EGL_NUM_PLATFORMS] = { 583464ebd5Sriastradh { _EGL_PLATFORM_WINDOWS, "gdi" }, 593464ebd5Sriastradh { _EGL_PLATFORM_X11, "x11" }, 603464ebd5Sriastradh { _EGL_PLATFORM_WAYLAND, "wayland" }, 613464ebd5Sriastradh { _EGL_PLATFORM_DRM, "drm" }, 623464ebd5Sriastradh { _EGL_PLATFORM_FBDEV, "fbdev" } 633464ebd5Sriastradh }; 643464ebd5Sriastradh _EGLPlatformType plat = _EGL_INVALID_PLATFORM; 653464ebd5Sriastradh const char *plat_name; 663464ebd5Sriastradh EGLint i; 673464ebd5Sriastradh 683464ebd5Sriastradh plat_name = getenv("EGL_PLATFORM"); 693464ebd5Sriastradh /* try deprecated env variable */ 703464ebd5Sriastradh if (!plat_name || !plat_name[0]) 713464ebd5Sriastradh plat_name = getenv("EGL_DISPLAY"); 723464ebd5Sriastradh if (!plat_name || !plat_name[0]) 733464ebd5Sriastradh return _EGL_INVALID_PLATFORM; 743464ebd5Sriastradh 753464ebd5Sriastradh for (i = 0; i < _EGL_NUM_PLATFORMS; i++) { 763464ebd5Sriastradh if (strcmp(egl_platforms[i].name, plat_name) == 0) { 773464ebd5Sriastradh plat = egl_platforms[i].platform; 783464ebd5Sriastradh break; 793464ebd5Sriastradh } 803464ebd5Sriastradh } 813464ebd5Sriastradh 823464ebd5Sriastradh return plat; 833464ebd5Sriastradh} 843464ebd5Sriastradh 853464ebd5Sriastradh 863464ebd5Sriastradh/** 873464ebd5Sriastradh * Return the native platform. It is the platform of the EGL native types. 883464ebd5Sriastradh */ 893464ebd5Sriastradh_EGLPlatformType 903464ebd5Sriastradh_eglGetNativePlatform(void) 913464ebd5Sriastradh{ 923464ebd5Sriastradh static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM; 933464ebd5Sriastradh 943464ebd5Sriastradh if (native_platform == _EGL_INVALID_PLATFORM) { 953464ebd5Sriastradh native_platform = _eglGetNativePlatformFromEnv(); 963464ebd5Sriastradh if (native_platform == _EGL_INVALID_PLATFORM) 973464ebd5Sriastradh native_platform = _EGL_NATIVE_PLATFORM; 983464ebd5Sriastradh } 993464ebd5Sriastradh 1003464ebd5Sriastradh return native_platform; 1013464ebd5Sriastradh} 1023464ebd5Sriastradh 1033464ebd5Sriastradh 1044a49301eSmrg/** 1054a49301eSmrg * Finish display management. 1064a49301eSmrg */ 1074a49301eSmrgvoid 1084a49301eSmrg_eglFiniDisplay(void) 1094a49301eSmrg{ 1104a49301eSmrg _EGLDisplay *dpyList, *dpy; 1114a49301eSmrg 1124a49301eSmrg /* atexit function is called with global mutex locked */ 1134a49301eSmrg dpyList = _eglGlobal.DisplayList; 1144a49301eSmrg while (dpyList) { 115cdc920a0Smrg EGLint i; 116cdc920a0Smrg 1174a49301eSmrg /* pop list head */ 1184a49301eSmrg dpy = dpyList; 1194a49301eSmrg dpyList = dpyList->Next; 1204a49301eSmrg 121cdc920a0Smrg for (i = 0; i < _EGL_NUM_RESOURCES; i++) { 122cdc920a0Smrg if (dpy->ResourceLists[i]) { 123cdc920a0Smrg _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy); 124cdc920a0Smrg break; 125cdc920a0Smrg } 126cdc920a0Smrg } 1274a49301eSmrg 1284a49301eSmrg free(dpy); 1294a49301eSmrg } 1304a49301eSmrg _eglGlobal.DisplayList = NULL; 1314a49301eSmrg} 1324a49301eSmrg 1334a49301eSmrg 1344a49301eSmrg/** 135cdc920a0Smrg * Find the display corresponding to the specified native display, or create a 136cdc920a0Smrg * new one. 1374a49301eSmrg */ 1384a49301eSmrg_EGLDisplay * 1393464ebd5Sriastradh_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy) 1404a49301eSmrg{ 1414a49301eSmrg _EGLDisplay *dpy; 1424a49301eSmrg 1433464ebd5Sriastradh if (plat == _EGL_INVALID_PLATFORM) 1443464ebd5Sriastradh return NULL; 1453464ebd5Sriastradh 1464a49301eSmrg _eglLockMutex(_eglGlobal.Mutex); 1474a49301eSmrg 148cdc920a0Smrg /* search the display list first */ 1494a49301eSmrg dpy = _eglGlobal.DisplayList; 1504a49301eSmrg while (dpy) { 1513464ebd5Sriastradh if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy) 152cdc920a0Smrg break; 1534a49301eSmrg dpy = dpy->Next; 1544a49301eSmrg } 1554a49301eSmrg 156cdc920a0Smrg /* create a new display */ 157cdc920a0Smrg if (!dpy) { 158cdc920a0Smrg dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay)); 159cdc920a0Smrg if (dpy) { 160cdc920a0Smrg _eglInitMutex(&dpy->Mutex); 1613464ebd5Sriastradh dpy->Platform = plat; 1623464ebd5Sriastradh dpy->PlatformDisplay = plat_dpy; 163cdc920a0Smrg 164cdc920a0Smrg /* add to the display list */ 165cdc920a0Smrg dpy->Next = _eglGlobal.DisplayList; 166cdc920a0Smrg _eglGlobal.DisplayList = dpy; 167cdc920a0Smrg } 168cdc920a0Smrg } 169cdc920a0Smrg 1704a49301eSmrg _eglUnlockMutex(_eglGlobal.Mutex); 1714a49301eSmrg 172cdc920a0Smrg return dpy; 1734a49301eSmrg} 1744a49301eSmrg 1754a49301eSmrg 1764a49301eSmrg/** 1774a49301eSmrg * Destroy the contexts and surfaces that are linked to the display. 1784a49301eSmrg */ 1794a49301eSmrgvoid 1804a49301eSmrg_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display) 1814a49301eSmrg{ 182cdc920a0Smrg _EGLResource *list; 1834a49301eSmrg 184cdc920a0Smrg list = display->ResourceLists[_EGL_RESOURCE_CONTEXT]; 185cdc920a0Smrg while (list) { 186cdc920a0Smrg _EGLContext *ctx = (_EGLContext *) list; 187cdc920a0Smrg list = list->Next; 1884a49301eSmrg 1894a49301eSmrg _eglUnlinkContext(ctx); 1904a49301eSmrg drv->API.DestroyContext(drv, display, ctx); 1914a49301eSmrg } 192cdc920a0Smrg assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]); 1934a49301eSmrg 194cdc920a0Smrg list = display->ResourceLists[_EGL_RESOURCE_SURFACE]; 195cdc920a0Smrg while (list) { 196cdc920a0Smrg _EGLSurface *surf = (_EGLSurface *) list; 197cdc920a0Smrg list = list->Next; 1984a49301eSmrg 1994a49301eSmrg _eglUnlinkSurface(surf); 2004a49301eSmrg drv->API.DestroySurface(drv, display, surf); 2014a49301eSmrg } 202cdc920a0Smrg assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]); 2034a49301eSmrg} 2044a49301eSmrg 2054a49301eSmrg 2064a49301eSmrg/** 2074a49301eSmrg * Free all the data hanging of an _EGLDisplay object, but not 2084a49301eSmrg * the object itself. 2094a49301eSmrg */ 2104a49301eSmrgvoid 2114a49301eSmrg_eglCleanupDisplay(_EGLDisplay *disp) 2124a49301eSmrg{ 2134a49301eSmrg if (disp->Configs) { 2143464ebd5Sriastradh _eglDestroyArray(disp->Configs, free); 2154a49301eSmrg disp->Configs = NULL; 2164a49301eSmrg } 2174a49301eSmrg 2184a49301eSmrg /* XXX incomplete */ 2194a49301eSmrg} 2204a49301eSmrg 2214a49301eSmrg 2224a49301eSmrg/** 2234a49301eSmrg * Return EGL_TRUE if the given handle is a valid handle to a display. 2244a49301eSmrg */ 2254a49301eSmrgEGLBoolean 2264a49301eSmrg_eglCheckDisplayHandle(EGLDisplay dpy) 2274a49301eSmrg{ 2284a49301eSmrg _EGLDisplay *cur; 2294a49301eSmrg 2304a49301eSmrg _eglLockMutex(_eglGlobal.Mutex); 2314a49301eSmrg cur = _eglGlobal.DisplayList; 2324a49301eSmrg while (cur) { 2334a49301eSmrg if (cur == (_EGLDisplay *) dpy) 2344a49301eSmrg break; 2354a49301eSmrg cur = cur->Next; 2364a49301eSmrg } 2374a49301eSmrg _eglUnlockMutex(_eglGlobal.Mutex); 2384a49301eSmrg return (cur != NULL); 2394a49301eSmrg} 2404a49301eSmrg 2414a49301eSmrg 2424a49301eSmrg/** 243cdc920a0Smrg * Return EGL_TRUE if the given resource is valid. That is, the display does 244cdc920a0Smrg * own the resource. 2454a49301eSmrg */ 2464a49301eSmrgEGLBoolean 247cdc920a0Smrg_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy) 2484a49301eSmrg{ 249cdc920a0Smrg _EGLResource *list = dpy->ResourceLists[type]; 250cdc920a0Smrg 251cdc920a0Smrg if (!res) 252cdc920a0Smrg return EGL_FALSE; 253cdc920a0Smrg 254cdc920a0Smrg while (list) { 255cdc920a0Smrg if (res == (void *) list) { 256cdc920a0Smrg assert(list->Display == dpy); 2574a49301eSmrg break; 2584a49301eSmrg } 259cdc920a0Smrg list = list->Next; 2604a49301eSmrg } 261cdc920a0Smrg 262cdc920a0Smrg return (list != NULL); 2634a49301eSmrg} 2644a49301eSmrg 2654a49301eSmrg 2664a49301eSmrg/** 2673464ebd5Sriastradh * Initialize a display resource. 2684a49301eSmrg */ 269cdc920a0Smrgvoid 2703464ebd5Sriastradh_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *dpy) 2714a49301eSmrg{ 2723464ebd5Sriastradh memset(res, 0, size); 273cdc920a0Smrg res->Display = dpy; 2743464ebd5Sriastradh res->RefCount = 1; 2753464ebd5Sriastradh} 2763464ebd5Sriastradh 2773464ebd5Sriastradh 2783464ebd5Sriastradh/** 2793464ebd5Sriastradh * Increment reference count for the resource. 2803464ebd5Sriastradh */ 2813464ebd5Sriastradhvoid 2823464ebd5Sriastradh_eglGetResource(_EGLResource *res) 2833464ebd5Sriastradh{ 2843464ebd5Sriastradh assert(res && res->RefCount > 0); 2853464ebd5Sriastradh /* hopefully a resource is always manipulated with its display locked */ 2863464ebd5Sriastradh res->RefCount++; 2873464ebd5Sriastradh} 2883464ebd5Sriastradh 2893464ebd5Sriastradh 2903464ebd5Sriastradh/** 2913464ebd5Sriastradh * Decrement reference count for the resource. 2923464ebd5Sriastradh */ 2933464ebd5SriastradhEGLBoolean 2943464ebd5Sriastradh_eglPutResource(_EGLResource *res) 2953464ebd5Sriastradh{ 2963464ebd5Sriastradh assert(res && res->RefCount > 0); 2973464ebd5Sriastradh res->RefCount--; 2983464ebd5Sriastradh return (!res->RefCount); 2993464ebd5Sriastradh} 3003464ebd5Sriastradh 3013464ebd5Sriastradh 3023464ebd5Sriastradh/** 3033464ebd5Sriastradh * Link a resource to its display. 3043464ebd5Sriastradh */ 3053464ebd5Sriastradhvoid 3063464ebd5Sriastradh_eglLinkResource(_EGLResource *res, _EGLResourceType type) 3073464ebd5Sriastradh{ 3083464ebd5Sriastradh assert(res->Display); 3093464ebd5Sriastradh 310cdc920a0Smrg res->IsLinked = EGL_TRUE; 3113464ebd5Sriastradh res->Next = res->Display->ResourceLists[type]; 3123464ebd5Sriastradh res->Display->ResourceLists[type] = res; 3133464ebd5Sriastradh _eglGetResource(res); 3144a49301eSmrg} 3154a49301eSmrg 3164a49301eSmrg 317cdc920a0Smrg/** 318cdc920a0Smrg * Unlink a linked resource from its display. 319cdc920a0Smrg */ 320cdc920a0Smrgvoid 321cdc920a0Smrg_eglUnlinkResource(_EGLResource *res, _EGLResourceType type) 322cdc920a0Smrg{ 323cdc920a0Smrg _EGLResource *prev; 324cdc920a0Smrg 325cdc920a0Smrg prev = res->Display->ResourceLists[type]; 326cdc920a0Smrg if (prev != res) { 327cdc920a0Smrg while (prev) { 328cdc920a0Smrg if (prev->Next == res) 329cdc920a0Smrg break; 330cdc920a0Smrg prev = prev->Next; 331cdc920a0Smrg } 332cdc920a0Smrg assert(prev); 333cdc920a0Smrg prev->Next = res->Next; 334cdc920a0Smrg } 335cdc920a0Smrg else { 336cdc920a0Smrg res->Display->ResourceLists[type] = res->Next; 337cdc920a0Smrg } 338cdc920a0Smrg 339cdc920a0Smrg res->Next = NULL; 340cdc920a0Smrg res->IsLinked = EGL_FALSE; 3413464ebd5Sriastradh _eglPutResource(res); 3423464ebd5Sriastradh 3433464ebd5Sriastradh /* We always unlink before destroy. The driver still owns a reference */ 3443464ebd5Sriastradh assert(res->RefCount); 345cdc920a0Smrg} 346