egldisplay.c revision 7e102996
13464ebd5Sriastradh/**************************************************************************
23464ebd5Sriastradh *
3af69d88dSmrg * Copyright 2008 VMware, Inc.
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>
3801e04c3fSmrg#include "c11/threads.h"
3901e04c3fSmrg#include "util/u_atomic.h"
4001e04c3fSmrg
414a49301eSmrg#include "eglcontext.h"
42af69d88dSmrg#include "eglcurrent.h"
434a49301eSmrg#include "eglsurface.h"
444a49301eSmrg#include "egldisplay.h"
454a49301eSmrg#include "egldriver.h"
464a49301eSmrg#include "eglglobals.h"
474a49301eSmrg#include "egllog.h"
4801e04c3fSmrg#include "eglimage.h"
4901e04c3fSmrg#include "eglsync.h"
504a49301eSmrg
51af69d88dSmrg/* Includes for _eglNativePlatformDetectNativeDisplay */
52af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM
53af69d88dSmrg#include <wayland-client.h>
54af69d88dSmrg#endif
55af69d88dSmrg#ifdef HAVE_DRM_PLATFORM
56af69d88dSmrg#include <gbm.h>
57af69d88dSmrg#endif
58af69d88dSmrg
59af69d88dSmrg
60af69d88dSmrg/**
617e102996Smaya * Map build-system platform names to platform types.
62af69d88dSmrg */
63af69d88dSmrgstatic const struct {
64af69d88dSmrg   _EGLPlatformType platform;
65af69d88dSmrg   const char *name;
66af69d88dSmrg} egl_platforms[_EGL_NUM_PLATFORMS] = {
67af69d88dSmrg   { _EGL_PLATFORM_X11, "x11" },
68af69d88dSmrg   { _EGL_PLATFORM_WAYLAND, "wayland" },
69af69d88dSmrg   { _EGL_PLATFORM_DRM, "drm" },
7001e04c3fSmrg   { _EGL_PLATFORM_ANDROID, "android" },
7101e04c3fSmrg   { _EGL_PLATFORM_HAIKU, "haiku" },
7201e04c3fSmrg   { _EGL_PLATFORM_SURFACELESS, "surfaceless" },
73af69d88dSmrg};
74af69d88dSmrg
754a49301eSmrg
763464ebd5Sriastradh/**
773464ebd5Sriastradh * Return the native platform by parsing EGL_PLATFORM.
783464ebd5Sriastradh */
793464ebd5Sriastradhstatic _EGLPlatformType
803464ebd5Sriastradh_eglGetNativePlatformFromEnv(void)
813464ebd5Sriastradh{
823464ebd5Sriastradh   _EGLPlatformType plat = _EGL_INVALID_PLATFORM;
833464ebd5Sriastradh   const char *plat_name;
843464ebd5Sriastradh   EGLint i;
853464ebd5Sriastradh
863464ebd5Sriastradh   plat_name = getenv("EGL_PLATFORM");
873464ebd5Sriastradh   /* try deprecated env variable */
883464ebd5Sriastradh   if (!plat_name || !plat_name[0])
893464ebd5Sriastradh      plat_name = getenv("EGL_DISPLAY");
903464ebd5Sriastradh   if (!plat_name || !plat_name[0])
913464ebd5Sriastradh      return _EGL_INVALID_PLATFORM;
923464ebd5Sriastradh
933464ebd5Sriastradh   for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
943464ebd5Sriastradh      if (strcmp(egl_platforms[i].name, plat_name) == 0) {
953464ebd5Sriastradh         plat = egl_platforms[i].platform;
963464ebd5Sriastradh         break;
973464ebd5Sriastradh      }
983464ebd5Sriastradh   }
993464ebd5Sriastradh
1003464ebd5Sriastradh   return plat;
1013464ebd5Sriastradh}
1023464ebd5Sriastradh
1033464ebd5Sriastradh
104af69d88dSmrg/**
105af69d88dSmrg * Try detecting native platform with the help of native display characteristcs.
106af69d88dSmrg */
107af69d88dSmrgstatic _EGLPlatformType
108af69d88dSmrg_eglNativePlatformDetectNativeDisplay(void *nativeDisplay)
109af69d88dSmrg{
110af69d88dSmrg   if (nativeDisplay == EGL_DEFAULT_DISPLAY)
111af69d88dSmrg      return _EGL_INVALID_PLATFORM;
112af69d88dSmrg
113af69d88dSmrg   if (_eglPointerIsDereferencable(nativeDisplay)) {
114af69d88dSmrg      void *first_pointer = *(void **) nativeDisplay;
115af69d88dSmrg
116af69d88dSmrg      (void) first_pointer; /* silence unused var warning */
117af69d88dSmrg
118af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM
119af69d88dSmrg      /* wl_display is a wl_proxy, which is a wl_object.
120af69d88dSmrg       * wl_object's first element points to the interfacetype. */
121af69d88dSmrg      if (first_pointer == &wl_display_interface)
122af69d88dSmrg         return _EGL_PLATFORM_WAYLAND;
123af69d88dSmrg#endif
124af69d88dSmrg
125af69d88dSmrg#ifdef HAVE_DRM_PLATFORM
126af69d88dSmrg      /* gbm has a pointer to its constructor as first element. */
127af69d88dSmrg      if (first_pointer == gbm_create_device)
128af69d88dSmrg         return _EGL_PLATFORM_DRM;
129af69d88dSmrg#endif
130af69d88dSmrg
131af69d88dSmrg#ifdef HAVE_X11_PLATFORM
132af69d88dSmrg      /* If not matched to any other platform, fallback to x11. */
133af69d88dSmrg      return _EGL_PLATFORM_X11;
134af69d88dSmrg#endif
13501e04c3fSmrg
13601e04c3fSmrg#ifdef HAVE_HAIKU_PLATFORM
13701e04c3fSmrg      return _EGL_PLATFORM_HAIKU;
13801e04c3fSmrg#endif
139af69d88dSmrg   }
140af69d88dSmrg
141af69d88dSmrg   return _EGL_INVALID_PLATFORM;
142af69d88dSmrg}
143af69d88dSmrg
144af69d88dSmrg
1453464ebd5Sriastradh/**
1463464ebd5Sriastradh * Return the native platform.  It is the platform of the EGL native types.
1473464ebd5Sriastradh */
1483464ebd5Sriastradh_EGLPlatformType
149af69d88dSmrg_eglGetNativePlatform(void *nativeDisplay)
1503464ebd5Sriastradh{
1513464ebd5Sriastradh   static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
15201e04c3fSmrg   _EGLPlatformType detected_platform = native_platform;
15301e04c3fSmrg
15401e04c3fSmrg   if (detected_platform == _EGL_INVALID_PLATFORM) {
15501e04c3fSmrg      const char *detection_method;
1563464ebd5Sriastradh
15701e04c3fSmrg      detected_platform = _eglGetNativePlatformFromEnv();
158af69d88dSmrg      detection_method = "environment overwrite";
15901e04c3fSmrg
16001e04c3fSmrg      if (detected_platform == _EGL_INVALID_PLATFORM) {
16101e04c3fSmrg         detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
162af69d88dSmrg         detection_method = "autodetected";
163af69d88dSmrg      }
1643464ebd5Sriastradh
16501e04c3fSmrg      if (detected_platform == _EGL_INVALID_PLATFORM) {
16601e04c3fSmrg         detected_platform = _EGL_NATIVE_PLATFORM;
16701e04c3fSmrg         detection_method = "build-time configuration";
16801e04c3fSmrg      }
16901e04c3fSmrg
170af69d88dSmrg      _eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
17101e04c3fSmrg              egl_platforms[detected_platform].name, detection_method);
17201e04c3fSmrg
17301e04c3fSmrg      p_atomic_cmpxchg(&native_platform, _EGL_INVALID_PLATFORM,
17401e04c3fSmrg                       detected_platform);
17501e04c3fSmrg   }
176af69d88dSmrg
1773464ebd5Sriastradh   return native_platform;
1783464ebd5Sriastradh}
1793464ebd5Sriastradh
1803464ebd5Sriastradh
1814a49301eSmrg/**
1824a49301eSmrg * Finish display management.
1834a49301eSmrg */
1844a49301eSmrgvoid
1854a49301eSmrg_eglFiniDisplay(void)
1864a49301eSmrg{
1877e102996Smaya   _EGLDisplay *dispList, *disp;
1884a49301eSmrg
1894a49301eSmrg   /* atexit function is called with global mutex locked */
1907e102996Smaya   dispList = _eglGlobal.DisplayList;
1917e102996Smaya   while (dispList) {
192cdc920a0Smrg      EGLint i;
193cdc920a0Smrg
1944a49301eSmrg      /* pop list head */
1957e102996Smaya      disp = dispList;
1967e102996Smaya      dispList = dispList->Next;
1974a49301eSmrg
198cdc920a0Smrg      for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
1997e102996Smaya         if (disp->ResourceLists[i]) {
2007e102996Smaya            _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", disp);
201cdc920a0Smrg            break;
202cdc920a0Smrg         }
203cdc920a0Smrg      }
2044a49301eSmrg
2057e102996Smaya      free(disp);
2064a49301eSmrg   }
2074a49301eSmrg   _eglGlobal.DisplayList = NULL;
2084a49301eSmrg}
2094a49301eSmrg
2104a49301eSmrg
2114a49301eSmrg/**
212cdc920a0Smrg * Find the display corresponding to the specified native display, or create a
213cdc920a0Smrg * new one.
2144a49301eSmrg */
2154a49301eSmrg_EGLDisplay *
2163464ebd5Sriastradh_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy)
2174a49301eSmrg{
2187e102996Smaya   _EGLDisplay *disp;
2194a49301eSmrg
2203464ebd5Sriastradh   if (plat == _EGL_INVALID_PLATFORM)
2213464ebd5Sriastradh      return NULL;
2223464ebd5Sriastradh
22301e04c3fSmrg   mtx_lock(_eglGlobal.Mutex);
2244a49301eSmrg
225cdc920a0Smrg   /* search the display list first */
2267e102996Smaya   disp = _eglGlobal.DisplayList;
2277e102996Smaya   while (disp) {
2287e102996Smaya      if (disp->Platform == plat && disp->PlatformDisplay == plat_dpy)
229cdc920a0Smrg         break;
2307e102996Smaya      disp = disp->Next;
2314a49301eSmrg   }
2324a49301eSmrg
233cdc920a0Smrg   /* create a new display */
2347e102996Smaya   if (!disp) {
2357e102996Smaya      disp = calloc(1, sizeof(_EGLDisplay));
2367e102996Smaya      if (disp) {
2377e102996Smaya         mtx_init(&disp->Mutex, mtx_plain);
2387e102996Smaya         disp->Platform = plat;
2397e102996Smaya         disp->PlatformDisplay = plat_dpy;
240cdc920a0Smrg
241cdc920a0Smrg         /* add to the display list */
2427e102996Smaya         disp->Next = _eglGlobal.DisplayList;
2437e102996Smaya         _eglGlobal.DisplayList = disp;
244cdc920a0Smrg      }
245cdc920a0Smrg   }
246cdc920a0Smrg
24701e04c3fSmrg   mtx_unlock(_eglGlobal.Mutex);
2484a49301eSmrg
2497e102996Smaya   return disp;
2504a49301eSmrg}
2514a49301eSmrg
2524a49301eSmrg
2534a49301eSmrg/**
2544a49301eSmrg * Destroy the contexts and surfaces that are linked to the display.
2554a49301eSmrg */
2564a49301eSmrgvoid
2574a49301eSmrg_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
2584a49301eSmrg{
259cdc920a0Smrg   _EGLResource *list;
2604a49301eSmrg
261cdc920a0Smrg   list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
262cdc920a0Smrg   while (list) {
263cdc920a0Smrg      _EGLContext *ctx = (_EGLContext *) list;
264cdc920a0Smrg      list = list->Next;
2654a49301eSmrg
2664a49301eSmrg      _eglUnlinkContext(ctx);
2674a49301eSmrg      drv->API.DestroyContext(drv, display, ctx);
2684a49301eSmrg   }
269cdc920a0Smrg   assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
2704a49301eSmrg
271cdc920a0Smrg   list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
272cdc920a0Smrg   while (list) {
273cdc920a0Smrg      _EGLSurface *surf = (_EGLSurface *) list;
274cdc920a0Smrg      list = list->Next;
2754a49301eSmrg
2764a49301eSmrg      _eglUnlinkSurface(surf);
2774a49301eSmrg      drv->API.DestroySurface(drv, display, surf);
2784a49301eSmrg   }
279cdc920a0Smrg   assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
28001e04c3fSmrg
28101e04c3fSmrg   list = display->ResourceLists[_EGL_RESOURCE_IMAGE];
28201e04c3fSmrg   while (list) {
28301e04c3fSmrg      _EGLImage *image = (_EGLImage *) list;
28401e04c3fSmrg      list = list->Next;
28501e04c3fSmrg
28601e04c3fSmrg      _eglUnlinkImage(image);
28701e04c3fSmrg      drv->API.DestroyImageKHR(drv, display, image);
28801e04c3fSmrg   }
28901e04c3fSmrg   assert(!display->ResourceLists[_EGL_RESOURCE_IMAGE]);
29001e04c3fSmrg
29101e04c3fSmrg   list = display->ResourceLists[_EGL_RESOURCE_SYNC];
29201e04c3fSmrg   while (list) {
29301e04c3fSmrg      _EGLSync *sync = (_EGLSync *) list;
29401e04c3fSmrg      list = list->Next;
29501e04c3fSmrg
29601e04c3fSmrg      _eglUnlinkSync(sync);
29701e04c3fSmrg      drv->API.DestroySyncKHR(drv, display, sync);
29801e04c3fSmrg   }
29901e04c3fSmrg   assert(!display->ResourceLists[_EGL_RESOURCE_SYNC]);
3004a49301eSmrg}
3014a49301eSmrg
3024a49301eSmrg
3034a49301eSmrg/**
3044a49301eSmrg * Free all the data hanging of an _EGLDisplay object, but not
3054a49301eSmrg * the object itself.
3064a49301eSmrg */
3074a49301eSmrgvoid
3084a49301eSmrg_eglCleanupDisplay(_EGLDisplay *disp)
3094a49301eSmrg{
3104a49301eSmrg   if (disp->Configs) {
3113464ebd5Sriastradh      _eglDestroyArray(disp->Configs, free);
3124a49301eSmrg      disp->Configs = NULL;
3134a49301eSmrg   }
3144a49301eSmrg
3154a49301eSmrg   /* XXX incomplete */
3164a49301eSmrg}
3174a49301eSmrg
3184a49301eSmrg
3194a49301eSmrg/**
3204a49301eSmrg * Return EGL_TRUE if the given handle is a valid handle to a display.
3214a49301eSmrg */
3224a49301eSmrgEGLBoolean
3234a49301eSmrg_eglCheckDisplayHandle(EGLDisplay dpy)
3244a49301eSmrg{
3254a49301eSmrg   _EGLDisplay *cur;
3264a49301eSmrg
32701e04c3fSmrg   mtx_lock(_eglGlobal.Mutex);
3284a49301eSmrg   cur = _eglGlobal.DisplayList;
3294a49301eSmrg   while (cur) {
3304a49301eSmrg      if (cur == (_EGLDisplay *) dpy)
3314a49301eSmrg         break;
3324a49301eSmrg      cur = cur->Next;
3334a49301eSmrg   }
33401e04c3fSmrg   mtx_unlock(_eglGlobal.Mutex);
3354a49301eSmrg   return (cur != NULL);
3364a49301eSmrg}
3374a49301eSmrg
3384a49301eSmrg
3394a49301eSmrg/**
340cdc920a0Smrg * Return EGL_TRUE if the given resource is valid.  That is, the display does
341cdc920a0Smrg * own the resource.
3424a49301eSmrg */
3434a49301eSmrgEGLBoolean
3447e102996Smaya_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *disp)
3454a49301eSmrg{
3467e102996Smaya   _EGLResource *list = disp->ResourceLists[type];
347cdc920a0Smrg
348cdc920a0Smrg   if (!res)
349cdc920a0Smrg      return EGL_FALSE;
350cdc920a0Smrg
351cdc920a0Smrg   while (list) {
352cdc920a0Smrg      if (res == (void *) list) {
3537e102996Smaya         assert(list->Display == disp);
3544a49301eSmrg         break;
3554a49301eSmrg      }
356cdc920a0Smrg      list = list->Next;
3574a49301eSmrg   }
358cdc920a0Smrg
359cdc920a0Smrg   return (list != NULL);
3604a49301eSmrg}
3614a49301eSmrg
3624a49301eSmrg
3634a49301eSmrg/**
364af69d88dSmrg * Initialize a display resource.  The size of the subclass object is
365af69d88dSmrg * specified.
366af69d88dSmrg *
367af69d88dSmrg * This is supposed to be called from the initializers of subclasses, such as
368af69d88dSmrg * _eglInitContext or _eglInitSurface.
3694a49301eSmrg */
370cdc920a0Smrgvoid
3717e102996Smaya_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *disp)
3724a49301eSmrg{
3733464ebd5Sriastradh   memset(res, 0, size);
3747e102996Smaya   res->Display = disp;
3753464ebd5Sriastradh   res->RefCount = 1;
3763464ebd5Sriastradh}
3773464ebd5Sriastradh
3783464ebd5Sriastradh
3793464ebd5Sriastradh/**
3803464ebd5Sriastradh * Increment reference count for the resource.
3813464ebd5Sriastradh */
3823464ebd5Sriastradhvoid
3833464ebd5Sriastradh_eglGetResource(_EGLResource *res)
3843464ebd5Sriastradh{
3853464ebd5Sriastradh   assert(res && res->RefCount > 0);
3863464ebd5Sriastradh   /* hopefully a resource is always manipulated with its display locked */
3873464ebd5Sriastradh   res->RefCount++;
3883464ebd5Sriastradh}
3893464ebd5Sriastradh
3903464ebd5Sriastradh
3913464ebd5Sriastradh/**
3923464ebd5Sriastradh * Decrement reference count for the resource.
3933464ebd5Sriastradh */
3943464ebd5SriastradhEGLBoolean
3953464ebd5Sriastradh_eglPutResource(_EGLResource *res)
3963464ebd5Sriastradh{
3973464ebd5Sriastradh   assert(res && res->RefCount > 0);
3983464ebd5Sriastradh   res->RefCount--;
3993464ebd5Sriastradh   return (!res->RefCount);
4003464ebd5Sriastradh}
4013464ebd5Sriastradh
4023464ebd5Sriastradh
4033464ebd5Sriastradh/**
4043464ebd5Sriastradh * Link a resource to its display.
4053464ebd5Sriastradh */
4063464ebd5Sriastradhvoid
4073464ebd5Sriastradh_eglLinkResource(_EGLResource *res, _EGLResourceType type)
4083464ebd5Sriastradh{
4093464ebd5Sriastradh   assert(res->Display);
4103464ebd5Sriastradh
411cdc920a0Smrg   res->IsLinked = EGL_TRUE;
4123464ebd5Sriastradh   res->Next = res->Display->ResourceLists[type];
4133464ebd5Sriastradh   res->Display->ResourceLists[type] = res;
4143464ebd5Sriastradh   _eglGetResource(res);
4154a49301eSmrg}
4164a49301eSmrg
4174a49301eSmrg
418cdc920a0Smrg/**
419cdc920a0Smrg * Unlink a linked resource from its display.
420cdc920a0Smrg */
421cdc920a0Smrgvoid
422cdc920a0Smrg_eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
423cdc920a0Smrg{
424cdc920a0Smrg   _EGLResource *prev;
425cdc920a0Smrg
426cdc920a0Smrg   prev = res->Display->ResourceLists[type];
427cdc920a0Smrg   if (prev != res) {
428cdc920a0Smrg      while (prev) {
429cdc920a0Smrg         if (prev->Next == res)
430cdc920a0Smrg            break;
431cdc920a0Smrg         prev = prev->Next;
432cdc920a0Smrg      }
433cdc920a0Smrg      assert(prev);
434cdc920a0Smrg      prev->Next = res->Next;
435cdc920a0Smrg   }
436cdc920a0Smrg   else {
437cdc920a0Smrg      res->Display->ResourceLists[type] = res->Next;
438cdc920a0Smrg   }
439cdc920a0Smrg
440cdc920a0Smrg   res->Next = NULL;
441cdc920a0Smrg   res->IsLinked = EGL_FALSE;
4423464ebd5Sriastradh   _eglPutResource(res);
4433464ebd5Sriastradh
4443464ebd5Sriastradh   /* We always unlink before destroy.  The driver still owns a reference */
4453464ebd5Sriastradh   assert(res->RefCount);
446cdc920a0Smrg}
447af69d88dSmrg
448af69d88dSmrg#ifdef HAVE_X11_PLATFORM
449af69d88dSmrgstatic EGLBoolean
45001e04c3fSmrg_eglParseX11DisplayAttribList(_EGLDisplay *display,
45101e04c3fSmrg                              const EGLAttrib *attrib_list)
452af69d88dSmrg{
453af69d88dSmrg   int i;
454af69d88dSmrg
455af69d88dSmrg   if (attrib_list == NULL) {
456af69d88dSmrg      return EGL_TRUE;
457af69d88dSmrg   }
458af69d88dSmrg
459af69d88dSmrg   for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
46001e04c3fSmrg      EGLAttrib attrib = attrib_list[i];
46101e04c3fSmrg      EGLAttrib value = attrib_list[i + 1];
462af69d88dSmrg
463af69d88dSmrg      /* EGL_EXT_platform_x11 recognizes exactly one attribute,
464af69d88dSmrg       * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
465af69d88dSmrg       */
46601e04c3fSmrg      if (attrib != EGL_PLATFORM_X11_SCREEN_EXT)
46701e04c3fSmrg         return _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
46801e04c3fSmrg
46901e04c3fSmrg      display->Options.Platform = (void *)(uintptr_t)value;
470af69d88dSmrg   }
471af69d88dSmrg
472af69d88dSmrg   return EGL_TRUE;
473af69d88dSmrg}
474af69d88dSmrg
475af69d88dSmrg_EGLDisplay*
476af69d88dSmrg_eglGetX11Display(Display *native_display,
47701e04c3fSmrg                  const EGLAttrib *attrib_list)
478af69d88dSmrg{
47901e04c3fSmrg   _EGLDisplay *display = _eglFindDisplay(_EGL_PLATFORM_X11,
48001e04c3fSmrg                                          native_display);
48101e04c3fSmrg
48201e04c3fSmrg   if (!display) {
48301e04c3fSmrg      _eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
484af69d88dSmrg      return NULL;
485af69d88dSmrg   }
486af69d88dSmrg
48701e04c3fSmrg   if (!_eglParseX11DisplayAttribList(display, attrib_list)) {
48801e04c3fSmrg      return NULL;
48901e04c3fSmrg   }
49001e04c3fSmrg
49101e04c3fSmrg   return display;
492af69d88dSmrg}
493af69d88dSmrg#endif /* HAVE_X11_PLATFORM */
494af69d88dSmrg
495af69d88dSmrg#ifdef HAVE_DRM_PLATFORM
496af69d88dSmrg_EGLDisplay*
497af69d88dSmrg_eglGetGbmDisplay(struct gbm_device *native_display,
49801e04c3fSmrg                  const EGLAttrib *attrib_list)
499af69d88dSmrg{
500af69d88dSmrg   /* EGL_MESA_platform_gbm recognizes no attributes. */
501af69d88dSmrg   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
502af69d88dSmrg      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
503af69d88dSmrg      return NULL;
504af69d88dSmrg   }
505af69d88dSmrg
506af69d88dSmrg   return _eglFindDisplay(_EGL_PLATFORM_DRM, native_display);
507af69d88dSmrg}
508af69d88dSmrg#endif /* HAVE_DRM_PLATFORM */
509af69d88dSmrg
510af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM
511af69d88dSmrg_EGLDisplay*
512af69d88dSmrg_eglGetWaylandDisplay(struct wl_display *native_display,
51301e04c3fSmrg                      const EGLAttrib *attrib_list)
514af69d88dSmrg{
515af69d88dSmrg   /* EGL_EXT_platform_wayland recognizes no attributes. */
516af69d88dSmrg   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
517af69d88dSmrg      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
518af69d88dSmrg      return NULL;
519af69d88dSmrg   }
520af69d88dSmrg
521af69d88dSmrg   return _eglFindDisplay(_EGL_PLATFORM_WAYLAND, native_display);
522af69d88dSmrg}
523af69d88dSmrg#endif /* HAVE_WAYLAND_PLATFORM */
52401e04c3fSmrg
52501e04c3fSmrg#ifdef HAVE_SURFACELESS_PLATFORM
52601e04c3fSmrg_EGLDisplay*
52701e04c3fSmrg_eglGetSurfacelessDisplay(void *native_display,
52801e04c3fSmrg                          const EGLAttrib *attrib_list)
52901e04c3fSmrg{
53001e04c3fSmrg   /* This platform has no native display. */
53101e04c3fSmrg   if (native_display != NULL) {
53201e04c3fSmrg      _eglError(EGL_BAD_PARAMETER, "eglGetPlatformDisplay");
53301e04c3fSmrg      return NULL;
53401e04c3fSmrg   }
53501e04c3fSmrg
53601e04c3fSmrg   /* This platform recognizes no display attributes. */
53701e04c3fSmrg   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
53801e04c3fSmrg      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
53901e04c3fSmrg      return NULL;
54001e04c3fSmrg   }
54101e04c3fSmrg
54201e04c3fSmrg   return _eglFindDisplay(_EGL_PLATFORM_SURFACELESS, native_display);
54301e04c3fSmrg}
54401e04c3fSmrg#endif /* HAVE_SURFACELESS_PLATFORM */
545