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"
46 /* Includes for _eglNativePlatformDetectNativeDisplay */
51 #ifdef HAVE_WAYLAND_PLATFORM
52 #include <wayland-client.h>
54 #ifdef HAVE_DRM_PLATFORM
57 #ifdef HAVE_FBDEV_PLATFORM
59 #include <sys/types.h>
65 * Map --with-egl-platforms names to platform types.
68 _EGLPlatformType platform
;
70 } egl_platforms
[_EGL_NUM_PLATFORMS
] = {
71 { _EGL_PLATFORM_WINDOWS
, "gdi" },
72 { _EGL_PLATFORM_X11
, "x11" },
73 { _EGL_PLATFORM_WAYLAND
, "wayland" },
74 { _EGL_PLATFORM_DRM
, "drm" },
75 { _EGL_PLATFORM_FBDEV
, "fbdev" },
76 { _EGL_PLATFORM_NULL
, "null" },
77 { _EGL_PLATFORM_ANDROID
, "android" }
82 * Return the native platform by parsing EGL_PLATFORM.
84 static _EGLPlatformType
85 _eglGetNativePlatformFromEnv(void)
87 _EGLPlatformType plat
= _EGL_INVALID_PLATFORM
;
88 const char *plat_name
;
91 plat_name
= getenv("EGL_PLATFORM");
92 /* try deprecated env variable */
93 if (!plat_name
|| !plat_name
[0])
94 plat_name
= getenv("EGL_DISPLAY");
95 if (!plat_name
|| !plat_name
[0])
96 return _EGL_INVALID_PLATFORM
;
98 for (i
= 0; i
< _EGL_NUM_PLATFORMS
; i
++) {
99 if (strcmp(egl_platforms
[i
].name
, plat_name
) == 0) {
100 plat
= egl_platforms
[i
].platform
;
110 * Perform validity checks on a generic pointer.
113 _eglPointerIsDereferencable(void *p
)
116 uintptr_t addr
= (uintptr_t) p
;
117 unsigned char valid
= 0;
118 const long page_size
= getpagesize();
123 /* align addr to page_size */
124 addr
&= ~(page_size
- 1);
126 if (mincore((void *) addr
, page_size
, &valid
) < 0) {
127 _eglLog(_EGL_DEBUG
, "mincore failed: %m");
131 return (valid
& 0x01) == 0x01;
139 * Try detecting native platform with the help of native display characteristcs.
141 static _EGLPlatformType
142 _eglNativePlatformDetectNativeDisplay(EGLNativeDisplayType nativeDisplay
)
144 #ifdef HAVE_FBDEV_PLATFORM
148 if (nativeDisplay
== EGL_DEFAULT_DISPLAY
)
149 return _EGL_INVALID_PLATFORM
;
151 #ifdef HAVE_FBDEV_PLATFORM
152 /* fbdev is the only platform that can be a file descriptor. */
153 if (fstat((intptr_t) nativeDisplay
, &buf
) == 0 && S_ISCHR(buf
.st_mode
))
154 return _EGL_PLATFORM_FBDEV
;
157 if (_eglPointerIsDereferencable(nativeDisplay
)) {
158 void *first_pointer
= *(void **) nativeDisplay
;
160 (void) first_pointer
; /* silence unused var warning */
162 #ifdef HAVE_WAYLAND_PLATFORM
163 /* wl_display is a wl_proxy, which is a wl_object.
164 * wl_object's first element points to the interfacetype. */
165 if (first_pointer
== &wl_display_interface
)
166 return _EGL_PLATFORM_WAYLAND
;
169 #ifdef HAVE_DRM_PLATFORM
170 /* gbm has a pointer to its constructor as first element. */
171 if (first_pointer
== gbm_create_device
)
172 return _EGL_PLATFORM_DRM
;
175 #ifdef HAVE_X11_PLATFORM
176 /* If not matched to any other platform, fallback to x11. */
177 return _EGL_PLATFORM_X11
;
181 return _EGL_INVALID_PLATFORM
;
186 * Return the native platform. It is the platform of the EGL native types.
189 _eglGetNativePlatform(EGLNativeDisplayType nativeDisplay
)
191 static _EGLPlatformType native_platform
= _EGL_INVALID_PLATFORM
;
192 char *detection_method
= NULL
;
194 if (native_platform
== _EGL_INVALID_PLATFORM
) {
195 native_platform
= _eglGetNativePlatformFromEnv();
196 detection_method
= "environment overwrite";
197 if (native_platform
== _EGL_INVALID_PLATFORM
) {
198 native_platform
= _eglNativePlatformDetectNativeDisplay(nativeDisplay
);
199 detection_method
= "autodetected";
200 if (native_platform
== _EGL_INVALID_PLATFORM
) {
201 native_platform
= _EGL_NATIVE_PLATFORM
;
202 detection_method
= "build-time configuration";
207 if (detection_method
!= NULL
)
208 _eglLog(_EGL_DEBUG
, "Native platform type: %s (%s)",
209 egl_platforms
[native_platform
].name
, detection_method
);
211 return native_platform
;
216 * Finish display management.
219 _eglFiniDisplay(void)
221 _EGLDisplay
*dpyList
, *dpy
;
223 /* atexit function is called with global mutex locked */
224 dpyList
= _eglGlobal
.DisplayList
;
230 dpyList
= dpyList
->Next
;
232 for (i
= 0; i
< _EGL_NUM_RESOURCES
; i
++) {
233 if (dpy
->ResourceLists
[i
]) {
234 _eglLog(_EGL_DEBUG
, "Display %p is destroyed with resources", dpy
);
241 _eglGlobal
.DisplayList
= NULL
;
246 * Find the display corresponding to the specified native display, or create a
250 _eglFindDisplay(_EGLPlatformType plat
, void *plat_dpy
)
254 if (plat
== _EGL_INVALID_PLATFORM
)
257 _eglLockMutex(_eglGlobal
.Mutex
);
259 /* search the display list first */
260 dpy
= _eglGlobal
.DisplayList
;
262 if (dpy
->Platform
== plat
&& dpy
->PlatformDisplay
== plat_dpy
)
267 /* create a new display */
269 dpy
= (_EGLDisplay
*) calloc(1, sizeof(_EGLDisplay
));
271 _eglInitMutex(&dpy
->Mutex
);
272 dpy
->Platform
= plat
;
273 dpy
->PlatformDisplay
= plat_dpy
;
275 /* add to the display list */
276 dpy
->Next
= _eglGlobal
.DisplayList
;
277 _eglGlobal
.DisplayList
= dpy
;
281 _eglUnlockMutex(_eglGlobal
.Mutex
);
288 * Destroy the contexts and surfaces that are linked to the display.
291 _eglReleaseDisplayResources(_EGLDriver
*drv
, _EGLDisplay
*display
)
295 list
= display
->ResourceLists
[_EGL_RESOURCE_CONTEXT
];
297 _EGLContext
*ctx
= (_EGLContext
*) list
;
300 _eglUnlinkContext(ctx
);
301 drv
->API
.DestroyContext(drv
, display
, ctx
);
303 assert(!display
->ResourceLists
[_EGL_RESOURCE_CONTEXT
]);
305 list
= display
->ResourceLists
[_EGL_RESOURCE_SURFACE
];
307 _EGLSurface
*surf
= (_EGLSurface
*) list
;
310 _eglUnlinkSurface(surf
);
311 drv
->API
.DestroySurface(drv
, display
, surf
);
313 assert(!display
->ResourceLists
[_EGL_RESOURCE_SURFACE
]);
318 * Free all the data hanging of an _EGLDisplay object, but not
322 _eglCleanupDisplay(_EGLDisplay
*disp
)
325 _eglDestroyArray(disp
->Configs
, free
);
326 disp
->Configs
= NULL
;
334 * Return EGL_TRUE if the given handle is a valid handle to a display.
337 _eglCheckDisplayHandle(EGLDisplay dpy
)
341 _eglLockMutex(_eglGlobal
.Mutex
);
342 cur
= _eglGlobal
.DisplayList
;
344 if (cur
== (_EGLDisplay
*) dpy
)
348 _eglUnlockMutex(_eglGlobal
.Mutex
);
349 return (cur
!= NULL
);
354 * Return EGL_TRUE if the given resource is valid. That is, the display does
358 _eglCheckResource(void *res
, _EGLResourceType type
, _EGLDisplay
*dpy
)
360 _EGLResource
*list
= dpy
->ResourceLists
[type
];
366 if (res
== (void *) list
) {
367 assert(list
->Display
== dpy
);
373 return (list
!= NULL
);
378 * Initialize a display resource.
381 _eglInitResource(_EGLResource
*res
, EGLint size
, _EGLDisplay
*dpy
)
383 memset(res
, 0, size
);
390 * Increment reference count for the resource.
393 _eglGetResource(_EGLResource
*res
)
395 assert(res
&& res
->RefCount
> 0);
396 /* hopefully a resource is always manipulated with its display locked */
402 * Decrement reference count for the resource.
405 _eglPutResource(_EGLResource
*res
)
407 assert(res
&& res
->RefCount
> 0);
409 return (!res
->RefCount
);
414 * Link a resource to its display.
417 _eglLinkResource(_EGLResource
*res
, _EGLResourceType type
)
419 assert(res
->Display
);
421 res
->IsLinked
= EGL_TRUE
;
422 res
->Next
= res
->Display
->ResourceLists
[type
];
423 res
->Display
->ResourceLists
[type
] = res
;
424 _eglGetResource(res
);
429 * Unlink a linked resource from its display.
432 _eglUnlinkResource(_EGLResource
*res
, _EGLResourceType type
)
436 prev
= res
->Display
->ResourceLists
[type
];
439 if (prev
->Next
== res
)
444 prev
->Next
= res
->Next
;
447 res
->Display
->ResourceLists
[type
] = res
->Next
;
451 res
->IsLinked
= EGL_FALSE
;
452 _eglPutResource(res
);
454 /* We always unlink before destroy. The driver still owns a reference */
455 assert(res
->RefCount
);