1 /**************************************************************************
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.
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:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
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.
28 **************************************************************************/
32 * Functions related to EGLDisplay.
38 #include "eglcontext.h"
39 #include "eglsurface.h"
40 #include "egldisplay.h"
41 #include "egldriver.h"
42 #include "eglglobals.h"
48 * Return the native platform by parsing EGL_PLATFORM.
50 static _EGLPlatformType
51 _eglGetNativePlatformFromEnv(void)
53 /* map --with-egl-platforms names to platform types */
55 _EGLPlatformType platform
;
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 { _EGL_PLATFORM_AROS
, "aros" }
65 _EGLPlatformType plat
= _EGL_INVALID_PLATFORM
;
66 const char *plat_name
;
69 plat_name
= getenv("EGL_PLATFORM");
70 /* try deprecated env variable */
71 if (!plat_name
|| !plat_name
[0])
72 plat_name
= getenv("EGL_DISPLAY");
73 if (!plat_name
|| !plat_name
[0])
74 return _EGL_INVALID_PLATFORM
;
76 for (i
= 0; i
< _EGL_NUM_PLATFORMS
; i
++) {
77 if (strcmp(egl_platforms
[i
].name
, plat_name
) == 0) {
78 plat
= egl_platforms
[i
].platform
;
88 * Return the native platform. It is the platform of the EGL native types.
91 _eglGetNativePlatform(void)
93 static _EGLPlatformType native_platform
= _EGL_INVALID_PLATFORM
;
95 if (native_platform
== _EGL_INVALID_PLATFORM
) {
96 native_platform
= _eglGetNativePlatformFromEnv();
97 if (native_platform
== _EGL_INVALID_PLATFORM
)
98 native_platform
= _EGL_NATIVE_PLATFORM
;
101 return native_platform
;
106 * Finish display management.
109 _eglFiniDisplay(void)
111 _EGLDisplay
*dpyList
, *dpy
;
113 /* atexit function is called with global mutex locked */
114 dpyList
= _eglGlobal
.DisplayList
;
120 dpyList
= dpyList
->Next
;
122 for (i
= 0; i
< _EGL_NUM_RESOURCES
; i
++) {
123 if (dpy
->ResourceLists
[i
]) {
124 _eglLog(_EGL_DEBUG
, "Display %p is destroyed with resources", dpy
);
131 _eglGlobal
.DisplayList
= NULL
;
136 * Find the display corresponding to the specified native display, or create a
140 _eglFindDisplay(_EGLPlatformType plat
, void *plat_dpy
)
144 if (plat
== _EGL_INVALID_PLATFORM
)
147 _eglLockMutex(_eglGlobal
.Mutex
);
149 /* search the display list first */
150 dpy
= _eglGlobal
.DisplayList
;
152 #if !defined(_EGL_OS_AROS)
153 /* It seems the _eglGlobal.DisplayList should unique per opener (not per task).
154 This is not true on AROS (_eglGlobal.DisplayList is global for all
155 openers). The workaround is to always create a new display object. This
156 might fail with multithreaded applications as they might expect to have
157 the same display object returned by GetDisplay */
158 if (dpy
->Platform
== plat
&& dpy
->PlatformDisplay
== plat_dpy
)
164 /* create a new display */
166 dpy
= (_EGLDisplay
*) calloc(1, sizeof(_EGLDisplay
));
168 _eglInitMutex(&dpy
->Mutex
);
169 dpy
->Platform
= plat
;
170 dpy
->PlatformDisplay
= plat_dpy
;
172 /* add to the display list */
173 dpy
->Next
= _eglGlobal
.DisplayList
;
174 _eglGlobal
.DisplayList
= dpy
;
178 _eglUnlockMutex(_eglGlobal
.Mutex
);
185 * Destroy the contexts and surfaces that are linked to the display.
188 _eglReleaseDisplayResources(_EGLDriver
*drv
, _EGLDisplay
*display
)
192 list
= display
->ResourceLists
[_EGL_RESOURCE_CONTEXT
];
194 _EGLContext
*ctx
= (_EGLContext
*) list
;
197 _eglUnlinkContext(ctx
);
198 drv
->API
.DestroyContext(drv
, display
, ctx
);
200 assert(!display
->ResourceLists
[_EGL_RESOURCE_CONTEXT
]);
202 list
= display
->ResourceLists
[_EGL_RESOURCE_SURFACE
];
204 _EGLSurface
*surf
= (_EGLSurface
*) list
;
207 _eglUnlinkSurface(surf
);
208 drv
->API
.DestroySurface(drv
, display
, surf
);
210 assert(!display
->ResourceLists
[_EGL_RESOURCE_SURFACE
]);
215 * Free all the data hanging of an _EGLDisplay object, but not
219 _eglCleanupDisplay(_EGLDisplay
*disp
)
222 _eglDestroyArray(disp
->Configs
, free
);
223 disp
->Configs
= NULL
;
231 * Return EGL_TRUE if the given handle is a valid handle to a display.
234 _eglCheckDisplayHandle(EGLDisplay dpy
)
238 _eglLockMutex(_eglGlobal
.Mutex
);
239 cur
= _eglGlobal
.DisplayList
;
241 if (cur
== (_EGLDisplay
*) dpy
)
245 _eglUnlockMutex(_eglGlobal
.Mutex
);
246 return (cur
!= NULL
);
251 * Return EGL_TRUE if the given resource is valid. That is, the display does
255 _eglCheckResource(void *res
, _EGLResourceType type
, _EGLDisplay
*dpy
)
257 _EGLResource
*list
= dpy
->ResourceLists
[type
];
263 if (res
== (void *) list
) {
264 assert(list
->Display
== dpy
);
270 return (list
!= NULL
);
275 * Initialize a display resource.
278 _eglInitResource(_EGLResource
*res
, EGLint size
, _EGLDisplay
*dpy
)
280 memset(res
, 0, size
);
287 * Increment reference count for the resource.
290 _eglGetResource(_EGLResource
*res
)
292 assert(res
&& res
->RefCount
> 0);
293 /* hopefully a resource is always manipulated with its display locked */
299 * Decrement reference count for the resource.
302 _eglPutResource(_EGLResource
*res
)
304 assert(res
&& res
->RefCount
> 0);
306 return (!res
->RefCount
);
311 * Link a resource to its display.
314 _eglLinkResource(_EGLResource
*res
, _EGLResourceType type
)
316 assert(res
->Display
);
318 res
->IsLinked
= EGL_TRUE
;
319 res
->Next
= res
->Display
->ResourceLists
[type
];
320 res
->Display
->ResourceLists
[type
] = res
;
321 _eglGetResource(res
);
326 * Unlink a linked resource from its display.
329 _eglUnlinkResource(_EGLResource
*res
, _EGLResourceType type
)
333 prev
= res
->Display
->ResourceLists
[type
];
336 if (prev
->Next
== res
)
341 prev
->Next
= res
->Next
;
344 res
->Display
->ResourceLists
[type
] = res
->Next
;
348 res
->IsLinked
= EGL_FALSE
;
349 _eglPutResource(res
);
351 /* We always unlink before destroy. The driver still owns a reference */
352 assert(res
->RefCount
);