egldisplay.c revision af69d88d
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>
384a49301eSmrg#include "eglcontext.h"
39af69d88dSmrg#include "eglcurrent.h"
404a49301eSmrg#include "eglsurface.h"
414a49301eSmrg#include "egldisplay.h"
424a49301eSmrg#include "egldriver.h"
434a49301eSmrg#include "eglglobals.h"
444a49301eSmrg#include "eglmutex.h"
454a49301eSmrg#include "egllog.h"
464a49301eSmrg
47af69d88dSmrg/* Includes for _eglNativePlatformDetectNativeDisplay */
48af69d88dSmrg#ifdef HAVE_MINCORE
49af69d88dSmrg#include <unistd.h>
50af69d88dSmrg#include <sys/mman.h>
51af69d88dSmrg#endif
52af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM
53af69d88dSmrg#include <wayland-client.h>
54af69d88dSmrg#endif
55af69d88dSmrg#ifdef HAVE_DRM_PLATFORM
56af69d88dSmrg#include <gbm.h>
57af69d88dSmrg#endif
58af69d88dSmrg#ifdef HAVE_FBDEV_PLATFORM
59af69d88dSmrg#include <stdint.h>
60af69d88dSmrg#include <sys/types.h>
61af69d88dSmrg#include <sys/stat.h>
62af69d88dSmrg#endif
63af69d88dSmrg
64af69d88dSmrg
65af69d88dSmrg/**
66af69d88dSmrg * Map --with-egl-platforms names to platform types.
67af69d88dSmrg */
68af69d88dSmrgstatic const struct {
69af69d88dSmrg   _EGLPlatformType platform;
70af69d88dSmrg   const char *name;
71af69d88dSmrg} egl_platforms[_EGL_NUM_PLATFORMS] = {
72af69d88dSmrg   { _EGL_PLATFORM_WINDOWS, "gdi" },
73af69d88dSmrg   { _EGL_PLATFORM_X11, "x11" },
74af69d88dSmrg   { _EGL_PLATFORM_WAYLAND, "wayland" },
75af69d88dSmrg   { _EGL_PLATFORM_DRM, "drm" },
76af69d88dSmrg   { _EGL_PLATFORM_FBDEV, "fbdev" },
77af69d88dSmrg   { _EGL_PLATFORM_NULL, "null" },
78af69d88dSmrg   { _EGL_PLATFORM_ANDROID, "android" }
79af69d88dSmrg};
80af69d88dSmrg
814a49301eSmrg
823464ebd5Sriastradh/**
833464ebd5Sriastradh * Return the native platform by parsing EGL_PLATFORM.
843464ebd5Sriastradh */
853464ebd5Sriastradhstatic _EGLPlatformType
863464ebd5Sriastradh_eglGetNativePlatformFromEnv(void)
873464ebd5Sriastradh{
883464ebd5Sriastradh   _EGLPlatformType plat = _EGL_INVALID_PLATFORM;
893464ebd5Sriastradh   const char *plat_name;
903464ebd5Sriastradh   EGLint i;
913464ebd5Sriastradh
923464ebd5Sriastradh   plat_name = getenv("EGL_PLATFORM");
933464ebd5Sriastradh   /* try deprecated env variable */
943464ebd5Sriastradh   if (!plat_name || !plat_name[0])
953464ebd5Sriastradh      plat_name = getenv("EGL_DISPLAY");
963464ebd5Sriastradh   if (!plat_name || !plat_name[0])
973464ebd5Sriastradh      return _EGL_INVALID_PLATFORM;
983464ebd5Sriastradh
993464ebd5Sriastradh   for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
1003464ebd5Sriastradh      if (strcmp(egl_platforms[i].name, plat_name) == 0) {
1013464ebd5Sriastradh         plat = egl_platforms[i].platform;
1023464ebd5Sriastradh         break;
1033464ebd5Sriastradh      }
1043464ebd5Sriastradh   }
1053464ebd5Sriastradh
1063464ebd5Sriastradh   return plat;
1073464ebd5Sriastradh}
1083464ebd5Sriastradh
1093464ebd5Sriastradh
110af69d88dSmrg/**
111af69d88dSmrg * Perform validity checks on a generic pointer.
112af69d88dSmrg */
113af69d88dSmrgstatic EGLBoolean
114af69d88dSmrg_eglPointerIsDereferencable(void *p)
115af69d88dSmrg{
116af69d88dSmrg#ifdef HAVE_MINCORE
117af69d88dSmrg   uintptr_t addr = (uintptr_t) p;
118af69d88dSmrg   unsigned char valid = 0;
119af69d88dSmrg   const long page_size = getpagesize();
120af69d88dSmrg
121af69d88dSmrg   if (p == NULL)
122af69d88dSmrg      return EGL_FALSE;
123af69d88dSmrg
124af69d88dSmrg   /* align addr to page_size */
125af69d88dSmrg   addr &= ~(page_size - 1);
126af69d88dSmrg
127af69d88dSmrg   if (mincore((void *) addr, page_size, &valid) < 0) {
128af69d88dSmrg      _eglLog(_EGL_DEBUG, "mincore failed: %m");
129af69d88dSmrg      return EGL_FALSE;
130af69d88dSmrg   }
131af69d88dSmrg
132af69d88dSmrg   return (valid & 0x01) == 0x01;
133af69d88dSmrg#else
134af69d88dSmrg   return p != NULL;
135af69d88dSmrg#endif
136af69d88dSmrg}
137af69d88dSmrg
138af69d88dSmrg
139af69d88dSmrg/**
140af69d88dSmrg * Try detecting native platform with the help of native display characteristcs.
141af69d88dSmrg */
142af69d88dSmrgstatic _EGLPlatformType
143af69d88dSmrg_eglNativePlatformDetectNativeDisplay(void *nativeDisplay)
144af69d88dSmrg{
145af69d88dSmrg#ifdef HAVE_FBDEV_PLATFORM
146af69d88dSmrg   struct stat buf;
147af69d88dSmrg#endif
148af69d88dSmrg
149af69d88dSmrg   if (nativeDisplay == EGL_DEFAULT_DISPLAY)
150af69d88dSmrg      return _EGL_INVALID_PLATFORM;
151af69d88dSmrg
152af69d88dSmrg#ifdef HAVE_FBDEV_PLATFORM
153af69d88dSmrg   /* fbdev is the only platform that can be a file descriptor. */
154af69d88dSmrg   if (fstat((intptr_t) nativeDisplay, &buf) == 0 && S_ISCHR(buf.st_mode))
155af69d88dSmrg      return _EGL_PLATFORM_FBDEV;
156af69d88dSmrg#endif
157af69d88dSmrg
158af69d88dSmrg   if (_eglPointerIsDereferencable(nativeDisplay)) {
159af69d88dSmrg      void *first_pointer = *(void **) nativeDisplay;
160af69d88dSmrg
161af69d88dSmrg      (void) first_pointer; /* silence unused var warning */
162af69d88dSmrg
163af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM
164af69d88dSmrg      /* wl_display is a wl_proxy, which is a wl_object.
165af69d88dSmrg       * wl_object's first element points to the interfacetype. */
166af69d88dSmrg      if (first_pointer == &wl_display_interface)
167af69d88dSmrg         return _EGL_PLATFORM_WAYLAND;
168af69d88dSmrg#endif
169af69d88dSmrg
170af69d88dSmrg#ifdef HAVE_DRM_PLATFORM
171af69d88dSmrg      /* gbm has a pointer to its constructor as first element. */
172af69d88dSmrg      if (first_pointer == gbm_create_device)
173af69d88dSmrg         return _EGL_PLATFORM_DRM;
174af69d88dSmrg#endif
175af69d88dSmrg
176af69d88dSmrg#ifdef HAVE_X11_PLATFORM
177af69d88dSmrg      /* If not matched to any other platform, fallback to x11. */
178af69d88dSmrg      return _EGL_PLATFORM_X11;
179af69d88dSmrg#endif
180af69d88dSmrg   }
181af69d88dSmrg
182af69d88dSmrg   return _EGL_INVALID_PLATFORM;
183af69d88dSmrg}
184af69d88dSmrg
185af69d88dSmrg
1863464ebd5Sriastradh/**
1873464ebd5Sriastradh * Return the native platform.  It is the platform of the EGL native types.
1883464ebd5Sriastradh */
1893464ebd5Sriastradh_EGLPlatformType
190af69d88dSmrg_eglGetNativePlatform(void *nativeDisplay)
1913464ebd5Sriastradh{
1923464ebd5Sriastradh   static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
193af69d88dSmrg   char *detection_method = NULL;
1943464ebd5Sriastradh
1953464ebd5Sriastradh   if (native_platform == _EGL_INVALID_PLATFORM) {
1963464ebd5Sriastradh      native_platform = _eglGetNativePlatformFromEnv();
197af69d88dSmrg      detection_method = "environment overwrite";
198af69d88dSmrg      if (native_platform == _EGL_INVALID_PLATFORM) {
199af69d88dSmrg         native_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
200af69d88dSmrg         detection_method = "autodetected";
201af69d88dSmrg         if (native_platform == _EGL_INVALID_PLATFORM) {
202af69d88dSmrg            native_platform = _EGL_NATIVE_PLATFORM;
203af69d88dSmrg            detection_method = "build-time configuration";
204af69d88dSmrg         }
205af69d88dSmrg      }
2063464ebd5Sriastradh   }
2073464ebd5Sriastradh
208af69d88dSmrg   if (detection_method != NULL)
209af69d88dSmrg      _eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
210af69d88dSmrg              egl_platforms[native_platform].name, detection_method);
211af69d88dSmrg
2123464ebd5Sriastradh   return native_platform;
2133464ebd5Sriastradh}
2143464ebd5Sriastradh
2153464ebd5Sriastradh
2164a49301eSmrg/**
2174a49301eSmrg * Finish display management.
2184a49301eSmrg */
2194a49301eSmrgvoid
2204a49301eSmrg_eglFiniDisplay(void)
2214a49301eSmrg{
2224a49301eSmrg   _EGLDisplay *dpyList, *dpy;
2234a49301eSmrg
2244a49301eSmrg   /* atexit function is called with global mutex locked */
2254a49301eSmrg   dpyList = _eglGlobal.DisplayList;
2264a49301eSmrg   while (dpyList) {
227cdc920a0Smrg      EGLint i;
228cdc920a0Smrg
2294a49301eSmrg      /* pop list head */
2304a49301eSmrg      dpy = dpyList;
2314a49301eSmrg      dpyList = dpyList->Next;
2324a49301eSmrg
233cdc920a0Smrg      for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
234cdc920a0Smrg         if (dpy->ResourceLists[i]) {
235cdc920a0Smrg            _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
236cdc920a0Smrg            break;
237cdc920a0Smrg         }
238cdc920a0Smrg      }
2394a49301eSmrg
2404a49301eSmrg      free(dpy);
2414a49301eSmrg   }
2424a49301eSmrg   _eglGlobal.DisplayList = NULL;
2434a49301eSmrg}
2444a49301eSmrg
2454a49301eSmrg
2464a49301eSmrg/**
247cdc920a0Smrg * Find the display corresponding to the specified native display, or create a
248cdc920a0Smrg * new one.
2494a49301eSmrg */
2504a49301eSmrg_EGLDisplay *
2513464ebd5Sriastradh_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy)
2524a49301eSmrg{
2534a49301eSmrg   _EGLDisplay *dpy;
2544a49301eSmrg
2553464ebd5Sriastradh   if (plat == _EGL_INVALID_PLATFORM)
2563464ebd5Sriastradh      return NULL;
2573464ebd5Sriastradh
2584a49301eSmrg   _eglLockMutex(_eglGlobal.Mutex);
2594a49301eSmrg
260cdc920a0Smrg   /* search the display list first */
2614a49301eSmrg   dpy = _eglGlobal.DisplayList;
2624a49301eSmrg   while (dpy) {
2633464ebd5Sriastradh      if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy)
264cdc920a0Smrg         break;
2654a49301eSmrg      dpy = dpy->Next;
2664a49301eSmrg   }
2674a49301eSmrg
268cdc920a0Smrg   /* create a new display */
269cdc920a0Smrg   if (!dpy) {
270af69d88dSmrg      dpy = calloc(1, sizeof(_EGLDisplay));
271cdc920a0Smrg      if (dpy) {
272cdc920a0Smrg         _eglInitMutex(&dpy->Mutex);
2733464ebd5Sriastradh         dpy->Platform = plat;
2743464ebd5Sriastradh         dpy->PlatformDisplay = plat_dpy;
275cdc920a0Smrg
276cdc920a0Smrg         /* add to the display list */
277cdc920a0Smrg         dpy->Next = _eglGlobal.DisplayList;
278cdc920a0Smrg         _eglGlobal.DisplayList = dpy;
279cdc920a0Smrg      }
280cdc920a0Smrg   }
281cdc920a0Smrg
2824a49301eSmrg   _eglUnlockMutex(_eglGlobal.Mutex);
2834a49301eSmrg
284cdc920a0Smrg   return dpy;
2854a49301eSmrg}
2864a49301eSmrg
2874a49301eSmrg
2884a49301eSmrg/**
2894a49301eSmrg * Destroy the contexts and surfaces that are linked to the display.
2904a49301eSmrg */
2914a49301eSmrgvoid
2924a49301eSmrg_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
2934a49301eSmrg{
294cdc920a0Smrg   _EGLResource *list;
2954a49301eSmrg
296cdc920a0Smrg   list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
297cdc920a0Smrg   while (list) {
298cdc920a0Smrg      _EGLContext *ctx = (_EGLContext *) list;
299cdc920a0Smrg      list = list->Next;
3004a49301eSmrg
3014a49301eSmrg      _eglUnlinkContext(ctx);
3024a49301eSmrg      drv->API.DestroyContext(drv, display, ctx);
3034a49301eSmrg   }
304cdc920a0Smrg   assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
3054a49301eSmrg
306cdc920a0Smrg   list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
307cdc920a0Smrg   while (list) {
308cdc920a0Smrg      _EGLSurface *surf = (_EGLSurface *) list;
309cdc920a0Smrg      list = list->Next;
3104a49301eSmrg
3114a49301eSmrg      _eglUnlinkSurface(surf);
3124a49301eSmrg      drv->API.DestroySurface(drv, display, surf);
3134a49301eSmrg   }
314cdc920a0Smrg   assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
3154a49301eSmrg}
3164a49301eSmrg
3174a49301eSmrg
3184a49301eSmrg/**
3194a49301eSmrg * Free all the data hanging of an _EGLDisplay object, but not
3204a49301eSmrg * the object itself.
3214a49301eSmrg */
3224a49301eSmrgvoid
3234a49301eSmrg_eglCleanupDisplay(_EGLDisplay *disp)
3244a49301eSmrg{
3254a49301eSmrg   if (disp->Configs) {
3263464ebd5Sriastradh      _eglDestroyArray(disp->Configs, free);
3274a49301eSmrg      disp->Configs = NULL;
3284a49301eSmrg   }
3294a49301eSmrg
3304a49301eSmrg   /* XXX incomplete */
3314a49301eSmrg}
3324a49301eSmrg
3334a49301eSmrg
3344a49301eSmrg/**
3354a49301eSmrg * Return EGL_TRUE if the given handle is a valid handle to a display.
3364a49301eSmrg */
3374a49301eSmrgEGLBoolean
3384a49301eSmrg_eglCheckDisplayHandle(EGLDisplay dpy)
3394a49301eSmrg{
3404a49301eSmrg   _EGLDisplay *cur;
3414a49301eSmrg
3424a49301eSmrg   _eglLockMutex(_eglGlobal.Mutex);
3434a49301eSmrg   cur = _eglGlobal.DisplayList;
3444a49301eSmrg   while (cur) {
3454a49301eSmrg      if (cur == (_EGLDisplay *) dpy)
3464a49301eSmrg         break;
3474a49301eSmrg      cur = cur->Next;
3484a49301eSmrg   }
3494a49301eSmrg   _eglUnlockMutex(_eglGlobal.Mutex);
3504a49301eSmrg   return (cur != NULL);
3514a49301eSmrg}
3524a49301eSmrg
3534a49301eSmrg
3544a49301eSmrg/**
355cdc920a0Smrg * Return EGL_TRUE if the given resource is valid.  That is, the display does
356cdc920a0Smrg * own the resource.
3574a49301eSmrg */
3584a49301eSmrgEGLBoolean
359cdc920a0Smrg_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy)
3604a49301eSmrg{
361cdc920a0Smrg   _EGLResource *list = dpy->ResourceLists[type];
362cdc920a0Smrg
363cdc920a0Smrg   if (!res)
364cdc920a0Smrg      return EGL_FALSE;
365cdc920a0Smrg
366cdc920a0Smrg   while (list) {
367cdc920a0Smrg      if (res == (void *) list) {
368cdc920a0Smrg         assert(list->Display == dpy);
3694a49301eSmrg         break;
3704a49301eSmrg      }
371cdc920a0Smrg      list = list->Next;
3724a49301eSmrg   }
373cdc920a0Smrg
374cdc920a0Smrg   return (list != NULL);
3754a49301eSmrg}
3764a49301eSmrg
3774a49301eSmrg
3784a49301eSmrg/**
379af69d88dSmrg * Initialize a display resource.  The size of the subclass object is
380af69d88dSmrg * specified.
381af69d88dSmrg *
382af69d88dSmrg * This is supposed to be called from the initializers of subclasses, such as
383af69d88dSmrg * _eglInitContext or _eglInitSurface.
3844a49301eSmrg */
385cdc920a0Smrgvoid
3863464ebd5Sriastradh_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *dpy)
3874a49301eSmrg{
3883464ebd5Sriastradh   memset(res, 0, size);
389cdc920a0Smrg   res->Display = dpy;
3903464ebd5Sriastradh   res->RefCount = 1;
3913464ebd5Sriastradh}
3923464ebd5Sriastradh
3933464ebd5Sriastradh
3943464ebd5Sriastradh/**
3953464ebd5Sriastradh * Increment reference count for the resource.
3963464ebd5Sriastradh */
3973464ebd5Sriastradhvoid
3983464ebd5Sriastradh_eglGetResource(_EGLResource *res)
3993464ebd5Sriastradh{
4003464ebd5Sriastradh   assert(res && res->RefCount > 0);
4013464ebd5Sriastradh   /* hopefully a resource is always manipulated with its display locked */
4023464ebd5Sriastradh   res->RefCount++;
4033464ebd5Sriastradh}
4043464ebd5Sriastradh
4053464ebd5Sriastradh
4063464ebd5Sriastradh/**
4073464ebd5Sriastradh * Decrement reference count for the resource.
4083464ebd5Sriastradh */
4093464ebd5SriastradhEGLBoolean
4103464ebd5Sriastradh_eglPutResource(_EGLResource *res)
4113464ebd5Sriastradh{
4123464ebd5Sriastradh   assert(res && res->RefCount > 0);
4133464ebd5Sriastradh   res->RefCount--;
4143464ebd5Sriastradh   return (!res->RefCount);
4153464ebd5Sriastradh}
4163464ebd5Sriastradh
4173464ebd5Sriastradh
4183464ebd5Sriastradh/**
4193464ebd5Sriastradh * Link a resource to its display.
4203464ebd5Sriastradh */
4213464ebd5Sriastradhvoid
4223464ebd5Sriastradh_eglLinkResource(_EGLResource *res, _EGLResourceType type)
4233464ebd5Sriastradh{
4243464ebd5Sriastradh   assert(res->Display);
4253464ebd5Sriastradh
426cdc920a0Smrg   res->IsLinked = EGL_TRUE;
4273464ebd5Sriastradh   res->Next = res->Display->ResourceLists[type];
4283464ebd5Sriastradh   res->Display->ResourceLists[type] = res;
4293464ebd5Sriastradh   _eglGetResource(res);
4304a49301eSmrg}
4314a49301eSmrg
4324a49301eSmrg
433cdc920a0Smrg/**
434cdc920a0Smrg * Unlink a linked resource from its display.
435cdc920a0Smrg */
436cdc920a0Smrgvoid
437cdc920a0Smrg_eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
438cdc920a0Smrg{
439cdc920a0Smrg   _EGLResource *prev;
440cdc920a0Smrg
441cdc920a0Smrg   prev = res->Display->ResourceLists[type];
442cdc920a0Smrg   if (prev != res) {
443cdc920a0Smrg      while (prev) {
444cdc920a0Smrg         if (prev->Next == res)
445cdc920a0Smrg            break;
446cdc920a0Smrg         prev = prev->Next;
447cdc920a0Smrg      }
448cdc920a0Smrg      assert(prev);
449cdc920a0Smrg      prev->Next = res->Next;
450cdc920a0Smrg   }
451cdc920a0Smrg   else {
452cdc920a0Smrg      res->Display->ResourceLists[type] = res->Next;
453cdc920a0Smrg   }
454cdc920a0Smrg
455cdc920a0Smrg   res->Next = NULL;
456cdc920a0Smrg   res->IsLinked = EGL_FALSE;
4573464ebd5Sriastradh   _eglPutResource(res);
4583464ebd5Sriastradh
4593464ebd5Sriastradh   /* We always unlink before destroy.  The driver still owns a reference */
4603464ebd5Sriastradh   assert(res->RefCount);
461cdc920a0Smrg}
462af69d88dSmrg
463af69d88dSmrg#ifdef HAVE_X11_PLATFORM
464af69d88dSmrgstatic EGLBoolean
465af69d88dSmrg_eglParseX11DisplayAttribList(const EGLint *attrib_list)
466af69d88dSmrg{
467af69d88dSmrg   int i;
468af69d88dSmrg
469af69d88dSmrg   if (attrib_list == NULL) {
470af69d88dSmrg      return EGL_TRUE;
471af69d88dSmrg   }
472af69d88dSmrg
473af69d88dSmrg   for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
474af69d88dSmrg      EGLint attrib = attrib_list[i];
475af69d88dSmrg      EGLint value = attrib_list[i + 1];
476af69d88dSmrg
477af69d88dSmrg      /* EGL_EXT_platform_x11 recognizes exactly one attribute,
478af69d88dSmrg       * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
479af69d88dSmrg       *
480af69d88dSmrg       * Mesa supports connecting to only the default screen, so we reject
481af69d88dSmrg       * screen != 0.
482af69d88dSmrg       */
483af69d88dSmrg      if (attrib != EGL_PLATFORM_X11_SCREEN_EXT || value != 0) {
484af69d88dSmrg         _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
485af69d88dSmrg         return EGL_FALSE;
486af69d88dSmrg      }
487af69d88dSmrg   }
488af69d88dSmrg
489af69d88dSmrg   return EGL_TRUE;
490af69d88dSmrg}
491af69d88dSmrg
492af69d88dSmrg_EGLDisplay*
493af69d88dSmrg_eglGetX11Display(Display *native_display,
494af69d88dSmrg                  const EGLint *attrib_list)
495af69d88dSmrg{
496af69d88dSmrg   if (!_eglParseX11DisplayAttribList(attrib_list)) {
497af69d88dSmrg      return NULL;
498af69d88dSmrg   }
499af69d88dSmrg
500af69d88dSmrg   return _eglFindDisplay(_EGL_PLATFORM_X11, native_display);
501af69d88dSmrg}
502af69d88dSmrg#endif /* HAVE_X11_PLATFORM */
503af69d88dSmrg
504af69d88dSmrg#ifdef HAVE_DRM_PLATFORM
505af69d88dSmrg_EGLDisplay*
506af69d88dSmrg_eglGetGbmDisplay(struct gbm_device *native_display,
507af69d88dSmrg                  const EGLint *attrib_list)
508af69d88dSmrg{
509af69d88dSmrg   /* EGL_MESA_platform_gbm recognizes no attributes. */
510af69d88dSmrg   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
511af69d88dSmrg      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
512af69d88dSmrg      return NULL;
513af69d88dSmrg   }
514af69d88dSmrg
515af69d88dSmrg   return _eglFindDisplay(_EGL_PLATFORM_DRM, native_display);
516af69d88dSmrg}
517af69d88dSmrg#endif /* HAVE_DRM_PLATFORM */
518af69d88dSmrg
519af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM
520af69d88dSmrg_EGLDisplay*
521af69d88dSmrg_eglGetWaylandDisplay(struct wl_display *native_display,
522af69d88dSmrg                      const EGLint *attrib_list)
523af69d88dSmrg{
524af69d88dSmrg   /* EGL_EXT_platform_wayland recognizes no attributes. */
525af69d88dSmrg   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
526af69d88dSmrg      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
527af69d88dSmrg      return NULL;
528af69d88dSmrg   }
529af69d88dSmrg
530af69d88dSmrg   return _eglFindDisplay(_EGL_PLATFORM_WAYLAND, native_display);
531af69d88dSmrg}
532af69d88dSmrg#endif /* HAVE_WAYLAND_PLATFORM */
533