1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
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 "c11/threads.h"
39 #include "util/u_atomic.h"
41 #include "eglcontext.h"
42 #include "eglcurrent.h"
43 #include "eglsurface.h"
44 #include "egldisplay.h"
45 #include "egldriver.h"
46 #include "eglglobals.h"
51 /* Includes for _eglNativePlatformDetectNativeDisplay */
52 #ifdef HAVE_WAYLAND_PLATFORM
53 #include <wayland-client.h>
55 #ifdef HAVE_DRM_PLATFORM
61 * Map --with-platforms names to platform types.
64 _EGLPlatformType platform
;
66 } egl_platforms
[_EGL_NUM_PLATFORMS
] = {
67 { _EGL_PLATFORM_X11
, "x11" },
68 { _EGL_PLATFORM_WAYLAND
, "wayland" },
69 { _EGL_PLATFORM_DRM
, "drm" },
70 { _EGL_PLATFORM_ANDROID
, "android" },
71 { _EGL_PLATFORM_HAIKU
, "haiku" },
72 { _EGL_PLATFORM_SURFACELESS
, "surfaceless" },
77 * Return the native platform by parsing EGL_PLATFORM.
79 static _EGLPlatformType
80 _eglGetNativePlatformFromEnv(void)
82 _EGLPlatformType plat
= _EGL_INVALID_PLATFORM
;
83 const char *plat_name
;
86 plat_name
= getenv("EGL_PLATFORM");
87 /* try deprecated env variable */
88 if (!plat_name
|| !plat_name
[0])
89 plat_name
= getenv("EGL_DISPLAY");
90 if (!plat_name
|| !plat_name
[0])
91 return _EGL_INVALID_PLATFORM
;
93 for (i
= 0; i
< _EGL_NUM_PLATFORMS
; i
++) {
94 if (strcmp(egl_platforms
[i
].name
, plat_name
) == 0) {
95 plat
= egl_platforms
[i
].platform
;
105 * Try detecting native platform with the help of native display characteristcs.
107 static _EGLPlatformType
108 _eglNativePlatformDetectNativeDisplay(void *nativeDisplay
)
110 if (nativeDisplay
== EGL_DEFAULT_DISPLAY
)
111 return _EGL_INVALID_PLATFORM
;
113 if (_eglPointerIsDereferencable(nativeDisplay
)) {
114 void *first_pointer
= *(void **) nativeDisplay
;
116 (void) first_pointer
; /* silence unused var warning */
118 #ifdef HAVE_WAYLAND_PLATFORM
119 /* wl_display is a wl_proxy, which is a wl_object.
120 * wl_object's first element points to the interfacetype. */
121 if (first_pointer
== &wl_display_interface
)
122 return _EGL_PLATFORM_WAYLAND
;
125 #ifdef HAVE_DRM_PLATFORM
126 /* gbm has a pointer to its constructor as first element. */
127 if (first_pointer
== gbm_create_device
)
128 return _EGL_PLATFORM_DRM
;
131 #ifdef HAVE_X11_PLATFORM
132 /* If not matched to any other platform, fallback to x11. */
133 return _EGL_PLATFORM_X11
;
136 #ifdef HAVE_HAIKU_PLATFORM
137 return _EGL_PLATFORM_HAIKU
;
141 return _EGL_INVALID_PLATFORM
;
146 * Return the native platform. It is the platform of the EGL native types.
149 _eglGetNativePlatform(void *nativeDisplay
)
151 static _EGLPlatformType native_platform
= _EGL_INVALID_PLATFORM
;
152 _EGLPlatformType detected_platform
= native_platform
;
154 if (detected_platform
== _EGL_INVALID_PLATFORM
) {
155 const char *detection_method
;
157 detected_platform
= _eglGetNativePlatformFromEnv();
158 detection_method
= "environment overwrite";
160 if (detected_platform
== _EGL_INVALID_PLATFORM
) {
161 detected_platform
= _eglNativePlatformDetectNativeDisplay(nativeDisplay
);
162 detection_method
= "autodetected";
165 if (detected_platform
== _EGL_INVALID_PLATFORM
) {
166 detected_platform
= _EGL_NATIVE_PLATFORM
;
167 detection_method
= "build-time configuration";
170 _eglLog(_EGL_DEBUG
, "Native platform type: %s (%s)",
171 egl_platforms
[detected_platform
].name
, detection_method
);
173 p_atomic_cmpxchg(&native_platform
, _EGL_INVALID_PLATFORM
,
177 return native_platform
;
182 * Finish display management.
185 _eglFiniDisplay(void)
187 _EGLDisplay
*dispList
, *disp
;
189 /* atexit function is called with global mutex locked */
190 dispList
= _eglGlobal
.DisplayList
;
196 dispList
= dispList
->Next
;
198 for (i
= 0; i
< _EGL_NUM_RESOURCES
; i
++) {
199 if (disp
->ResourceLists
[i
]) {
200 _eglLog(_EGL_DEBUG
, "Display %p is destroyed with resources", disp
);
207 _eglGlobal
.DisplayList
= NULL
;
212 * Find the display corresponding to the specified native display, or create a
216 _eglFindDisplay(_EGLPlatformType plat
, void *plat_dpy
)
220 if (plat
== _EGL_INVALID_PLATFORM
)
223 mtx_lock(_eglGlobal
.Mutex
);
225 /* search the display list first */
226 disp
= _eglGlobal
.DisplayList
;
228 if (disp
->Platform
== plat
&& disp
->PlatformDisplay
== plat_dpy
)
233 /* create a new display */
235 disp
= calloc(1, sizeof(_EGLDisplay
));
237 mtx_init(&disp
->Mutex
, mtx_plain
);
238 disp
->Platform
= plat
;
239 disp
->PlatformDisplay
= plat_dpy
;
241 /* add to the display list */
242 disp
->Next
= _eglGlobal
.DisplayList
;
243 _eglGlobal
.DisplayList
= disp
;
247 mtx_unlock(_eglGlobal
.Mutex
);
254 * Destroy the contexts and surfaces that are linked to the display.
257 _eglReleaseDisplayResources(_EGLDriver
*drv
, _EGLDisplay
*display
)
261 list
= display
->ResourceLists
[_EGL_RESOURCE_CONTEXT
];
263 _EGLContext
*ctx
= (_EGLContext
*) list
;
266 _eglUnlinkContext(ctx
);
267 drv
->API
.DestroyContext(drv
, display
, ctx
);
269 assert(!display
->ResourceLists
[_EGL_RESOURCE_CONTEXT
]);
271 list
= display
->ResourceLists
[_EGL_RESOURCE_SURFACE
];
273 _EGLSurface
*surf
= (_EGLSurface
*) list
;
276 _eglUnlinkSurface(surf
);
277 drv
->API
.DestroySurface(drv
, display
, surf
);
279 assert(!display
->ResourceLists
[_EGL_RESOURCE_SURFACE
]);
281 list
= display
->ResourceLists
[_EGL_RESOURCE_IMAGE
];
283 _EGLImage
*image
= (_EGLImage
*) list
;
286 _eglUnlinkImage(image
);
287 drv
->API
.DestroyImageKHR(drv
, display
, image
);
289 assert(!display
->ResourceLists
[_EGL_RESOURCE_IMAGE
]);
291 list
= display
->ResourceLists
[_EGL_RESOURCE_SYNC
];
293 _EGLSync
*sync
= (_EGLSync
*) list
;
296 _eglUnlinkSync(sync
);
297 drv
->API
.DestroySyncKHR(drv
, display
, sync
);
299 assert(!display
->ResourceLists
[_EGL_RESOURCE_SYNC
]);
304 * Free all the data hanging of an _EGLDisplay object, but not
308 _eglCleanupDisplay(_EGLDisplay
*disp
)
311 _eglDestroyArray(disp
->Configs
, free
);
312 disp
->Configs
= NULL
;
320 * Return EGL_TRUE if the given handle is a valid handle to a display.
323 _eglCheckDisplayHandle(EGLDisplay dpy
)
327 mtx_lock(_eglGlobal
.Mutex
);
328 cur
= _eglGlobal
.DisplayList
;
330 if (cur
== (_EGLDisplay
*) dpy
)
334 mtx_unlock(_eglGlobal
.Mutex
);
335 return (cur
!= NULL
);
340 * Return EGL_TRUE if the given resource is valid. That is, the display does
344 _eglCheckResource(void *res
, _EGLResourceType type
, _EGLDisplay
*disp
)
346 _EGLResource
*list
= disp
->ResourceLists
[type
];
352 if (res
== (void *) list
) {
353 assert(list
->Display
== disp
);
359 return (list
!= NULL
);
364 * Initialize a display resource. The size of the subclass object is
367 * This is supposed to be called from the initializers of subclasses, such as
368 * _eglInitContext or _eglInitSurface.
371 _eglInitResource(_EGLResource
*res
, EGLint size
, _EGLDisplay
*disp
)
373 memset(res
, 0, size
);
380 * Increment reference count for the resource.
383 _eglGetResource(_EGLResource
*res
)
385 assert(res
&& res
->RefCount
> 0);
386 /* hopefully a resource is always manipulated with its display locked */
392 * Decrement reference count for the resource.
395 _eglPutResource(_EGLResource
*res
)
397 assert(res
&& res
->RefCount
> 0);
399 return (!res
->RefCount
);
404 * Link a resource to its display.
407 _eglLinkResource(_EGLResource
*res
, _EGLResourceType type
)
409 assert(res
->Display
);
411 res
->IsLinked
= EGL_TRUE
;
412 res
->Next
= res
->Display
->ResourceLists
[type
];
413 res
->Display
->ResourceLists
[type
] = res
;
414 _eglGetResource(res
);
419 * Unlink a linked resource from its display.
422 _eglUnlinkResource(_EGLResource
*res
, _EGLResourceType type
)
426 prev
= res
->Display
->ResourceLists
[type
];
429 if (prev
->Next
== res
)
434 prev
->Next
= res
->Next
;
437 res
->Display
->ResourceLists
[type
] = res
->Next
;
441 res
->IsLinked
= EGL_FALSE
;
442 _eglPutResource(res
);
444 /* We always unlink before destroy. The driver still owns a reference */
445 assert(res
->RefCount
);
448 #ifdef HAVE_X11_PLATFORM
450 _eglParseX11DisplayAttribList(_EGLDisplay
*display
,
451 const EGLAttrib
*attrib_list
)
455 if (attrib_list
== NULL
) {
459 for (i
= 0; attrib_list
[i
] != EGL_NONE
; i
+= 2) {
460 EGLAttrib attrib
= attrib_list
[i
];
461 EGLAttrib value
= attrib_list
[i
+ 1];
463 /* EGL_EXT_platform_x11 recognizes exactly one attribute,
464 * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
466 if (attrib
!= EGL_PLATFORM_X11_SCREEN_EXT
)
467 return _eglError(EGL_BAD_ATTRIBUTE
, "eglGetPlatformDisplay");
469 display
->Options
.Platform
= (void *)(uintptr_t)value
;
476 _eglGetX11Display(Display
*native_display
,
477 const EGLAttrib
*attrib_list
)
479 _EGLDisplay
*display
= _eglFindDisplay(_EGL_PLATFORM_X11
,
483 _eglError(EGL_BAD_ALLOC
, "eglGetPlatformDisplay");
487 if (!_eglParseX11DisplayAttribList(display
, attrib_list
)) {
493 #endif /* HAVE_X11_PLATFORM */
495 #ifdef HAVE_DRM_PLATFORM
497 _eglGetGbmDisplay(struct gbm_device
*native_display
,
498 const EGLAttrib
*attrib_list
)
500 /* EGL_MESA_platform_gbm recognizes no attributes. */
501 if (attrib_list
!= NULL
&& attrib_list
[0] != EGL_NONE
) {
502 _eglError(EGL_BAD_ATTRIBUTE
, "eglGetPlatformDisplay");
506 return _eglFindDisplay(_EGL_PLATFORM_DRM
, native_display
);
508 #endif /* HAVE_DRM_PLATFORM */
510 #ifdef HAVE_WAYLAND_PLATFORM
512 _eglGetWaylandDisplay(struct wl_display
*native_display
,
513 const EGLAttrib
*attrib_list
)
515 /* EGL_EXT_platform_wayland recognizes no attributes. */
516 if (attrib_list
!= NULL
&& attrib_list
[0] != EGL_NONE
) {
517 _eglError(EGL_BAD_ATTRIBUTE
, "eglGetPlatformDisplay");
521 return _eglFindDisplay(_EGL_PLATFORM_WAYLAND
, native_display
);
523 #endif /* HAVE_WAYLAND_PLATFORM */
525 #ifdef HAVE_SURFACELESS_PLATFORM
527 _eglGetSurfacelessDisplay(void *native_display
,
528 const EGLAttrib
*attrib_list
)
530 /* This platform has no native display. */
531 if (native_display
!= NULL
) {
532 _eglError(EGL_BAD_PARAMETER
, "eglGetPlatformDisplay");
536 /* This platform recognizes no display attributes. */
537 if (attrib_list
!= NULL
&& attrib_list
[0] != EGL_NONE
) {
538 _eglError(EGL_BAD_ATTRIBUTE
, "eglGetPlatformDisplay");
542 return _eglFindDisplay(_EGL_PLATFORM_SURFACELESS
, native_display
);
544 #endif /* HAVE_SURFACELESS_PLATFORM */