egl: replace _EGLDriver param with _EGLDisplay->Driver in _eglReleaseDisplayResources()
[mesa.git] / src / egl / main / egldisplay.c
index 418ab0ec9b871a12a80ee212cf9e44752141aeb9..ac05f6f9fff14805519678f9ea8044c4915ccdb8 100644 (file)
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include "c11/threads.h"
+#include "util/macros.h"
+#include "util/os_file.h"
 #include "util/u_atomic.h"
 
 #include "eglcontext.h"
 #include "eglcurrent.h"
 #include "eglsurface.h"
+#include "egldevice.h"
 #include "egldisplay.h"
 #include "egldriver.h"
 #include "eglglobals.h"
 static const struct {
    _EGLPlatformType platform;
    const char *name;
-} egl_platforms[_EGL_NUM_PLATFORMS] = {
+} egl_platforms[] = {
    { _EGL_PLATFORM_X11, "x11" },
    { _EGL_PLATFORM_WAYLAND, "wayland" },
    { _EGL_PLATFORM_DRM, "drm" },
    { _EGL_PLATFORM_ANDROID, "android" },
    { _EGL_PLATFORM_HAIKU, "haiku" },
    { _EGL_PLATFORM_SURFACELESS, "surfaceless" },
+   { _EGL_PLATFORM_DEVICE, "device" },
 };
 
 
@@ -83,6 +89,9 @@ _eglGetNativePlatformFromEnv(void)
    const char *plat_name;
    EGLint i;
 
+   static_assert(ARRAY_SIZE(egl_platforms) == _EGL_NUM_PLATFORMS,
+                 "Missing platform");
+
    plat_name = getenv("EGL_PLATFORM");
    /* try deprecated env variable */
    if (!plat_name || !plat_name[0])
@@ -90,13 +99,16 @@ _eglGetNativePlatformFromEnv(void)
    if (!plat_name || !plat_name[0])
       return _EGL_INVALID_PLATFORM;
 
-   for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
+   for (i = 0; i < ARRAY_SIZE(egl_platforms); i++) {
       if (strcmp(egl_platforms[i].name, plat_name) == 0) {
          plat = egl_platforms[i].platform;
          break;
       }
    }
 
+   if (plat == _EGL_INVALID_PLATFORM)
+      _eglLog(_EGL_WARNING, "invalid EGL_PLATFORM given");
+
    return plat;
 }
 
@@ -127,15 +139,6 @@ _eglNativePlatformDetectNativeDisplay(void *nativeDisplay)
       if (first_pointer == gbm_create_device)
          return _EGL_PLATFORM_DRM;
 #endif
-
-#ifdef HAVE_X11_PLATFORM
-      /* If not matched to any other platform, fallback to x11. */
-      return _EGL_PLATFORM_X11;
-#endif
-
-#ifdef HAVE_HAIKU_PLATFORM
-      return _EGL_PLATFORM_HAIKU;
-#endif
    }
 
    return _EGL_INVALID_PLATFORM;
@@ -148,33 +151,23 @@ _eglNativePlatformDetectNativeDisplay(void *nativeDisplay)
 _EGLPlatformType
 _eglGetNativePlatform(void *nativeDisplay)
 {
-   static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
-   _EGLPlatformType detected_platform = native_platform;
+   _EGLPlatformType detected_platform = _eglGetNativePlatformFromEnv();
+   const char *detection_method = "environment";
 
    if (detected_platform == _EGL_INVALID_PLATFORM) {
-      const char *detection_method;
-
-      detected_platform = _eglGetNativePlatformFromEnv();
-      detection_method = "environment overwrite";
-
-      if (detected_platform == _EGL_INVALID_PLATFORM) {
-         detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
-         detection_method = "autodetected";
-      }
-
-      if (detected_platform == _EGL_INVALID_PLATFORM) {
-         detected_platform = _EGL_NATIVE_PLATFORM;
-         detection_method = "build-time configuration";
-      }
-
-      _eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
-              egl_platforms[detected_platform].name, detection_method);
+      detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
+      detection_method = "autodetected";
+   }
 
-      p_atomic_cmpxchg(&native_platform, _EGL_INVALID_PLATFORM,
-                       detected_platform);
+   if (detected_platform == _EGL_INVALID_PLATFORM) {
+      detected_platform = _EGL_NATIVE_PLATFORM;
+      detection_method = "build-time configuration";
    }
 
-   return native_platform;
+   _eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
+           egl_platforms[detected_platform].name, detection_method);
+
+   return detected_platform;
 }
 
 
@@ -202,6 +195,13 @@ _eglFiniDisplay(void)
          }
       }
 
+
+      /* The fcntl() code in _eglGetDeviceDisplay() ensures that valid fd >= 3,
+       * and invalid one is 0.
+       */
+      if (disp->Options.fd)
+         close(disp->Options.fd);
+
       free(disp->Options.Attribs);
       free(disp);
    }
@@ -223,7 +223,7 @@ _eglSameAttribs(const EGLAttrib *a, const EGLAttrib *b)
       return EGL_TRUE;
 
    /* otherwise, compare the lists */
-   return memcmp(a, b, na) == 0 ? EGL_TRUE : EGL_FALSE;
+   return memcmp(a, b, na * sizeof(a[0])) == 0 ? EGL_TRUE : EGL_FALSE;
 }
 
 /**
@@ -252,12 +252,10 @@ _eglFindDisplay(_EGLPlatformType plat, void *plat_dpy,
    mtx_lock(_eglGlobal.Mutex);
 
    /* search the display list first */
-   disp = _eglGlobal.DisplayList;
-   while (disp) {
+   for (disp = _eglGlobal.DisplayList; disp; disp = disp->Next) {
       if (disp->Platform == plat && disp->PlatformDisplay == plat_dpy &&
           _eglSameAttribs(disp->Options.Attribs, attrib_list))
          break;
-      disp = disp->Next;
    }
 
    /* create a new display */
@@ -295,9 +293,10 @@ out:
  * Destroy the contexts and surfaces that are linked to the display.
  */
 void
-_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
+_eglReleaseDisplayResources(_EGLDisplay *display)
 {
    _EGLResource *list;
+   const _EGLDriver *drv = display->Driver;
 
    list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
    while (list) {
@@ -305,7 +304,7 @@ _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
       list = list->Next;
 
       _eglUnlinkContext(ctx);
-      drv->API.DestroyContext(drv, display, ctx);
+      drv->DestroyContext(drv, display, ctx);
    }
    assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
 
@@ -315,7 +314,7 @@ _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
       list = list->Next;
 
       _eglUnlinkSurface(surf);
-      drv->API.DestroySurface(drv, display, surf);
+      drv->DestroySurface(drv, display, surf);
    }
    assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
 
@@ -325,7 +324,7 @@ _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
       list = list->Next;
 
       _eglUnlinkImage(image);
-      drv->API.DestroyImageKHR(drv, display, image);
+      drv->DestroyImageKHR(drv, display, image);
    }
    assert(!display->ResourceLists[_EGL_RESOURCE_IMAGE]);
 
@@ -335,7 +334,7 @@ _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
       list = list->Next;
 
       _eglUnlinkSync(sync);
-      drv->API.DestroySyncKHR(drv, display, sync);
+      drv->DestroySyncKHR(drv, display, sync);
    }
    assert(!display->ResourceLists[_EGL_RESOURCE_SYNC]);
 }
@@ -487,45 +486,22 @@ _eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
 }
 
 #ifdef HAVE_X11_PLATFORM
-static EGLBoolean
-_eglParseX11DisplayAttribList(_EGLDisplay *display,
-                              const EGLAttrib *attrib_list)
-{
-   int i;
-
-   if (attrib_list == NULL) {
-      return EGL_TRUE;
-   }
-
-   /* EGL_EXT_platform_x11 recognizes exactly one attribute,
-    * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
-    */
-   for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
-      if (attrib_list[i] != EGL_PLATFORM_X11_SCREEN_EXT)
-         return _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
-   }
-
-   return EGL_TRUE;
-}
-
 _EGLDisplay*
 _eglGetX11Display(Display *native_display,
                   const EGLAttrib *attrib_list)
 {
-   _EGLDisplay *display = _eglFindDisplay(_EGL_PLATFORM_X11,
-                                          native_display,
-                                          attrib_list);
-
-   if (!display) {
-      _eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
-      return NULL;
-   }
-
-   if (!_eglParseX11DisplayAttribList(display, attrib_list)) {
-      return NULL;
+   /* EGL_EXT_platform_x11 recognizes exactly one attribute,
+    * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
+    */
+   if (attrib_list != NULL) {
+      for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+         if (attrib_list[i] != EGL_PLATFORM_X11_SCREEN_EXT) {
+            _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+            return NULL;
+         }
+      }
    }
-
-   return display;
+   return _eglFindDisplay(_EGL_PLATFORM_X11, native_display, attrib_list);
 }
 #endif /* HAVE_X11_PLATFORM */
 
@@ -559,7 +535,6 @@ _eglGetWaylandDisplay(struct wl_display *native_display,
 }
 #endif /* HAVE_WAYLAND_PLATFORM */
 
-#ifdef HAVE_SURFACELESS_PLATFORM
 _EGLDisplay*
 _eglGetSurfacelessDisplay(void *native_display,
                           const EGLAttrib *attrib_list)
@@ -579,4 +554,77 @@ _eglGetSurfacelessDisplay(void *native_display,
    return _eglFindDisplay(_EGL_PLATFORM_SURFACELESS, native_display,
                           attrib_list);
 }
-#endif /* HAVE_SURFACELESS_PLATFORM */
+
+#ifdef HAVE_ANDROID_PLATFORM
+_EGLDisplay*
+_eglGetAndroidDisplay(void *native_display,
+                          const EGLAttrib *attrib_list)
+{
+
+   /* This platform recognizes no display attributes. */
+   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
+      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+      return NULL;
+   }
+
+   return _eglFindDisplay(_EGL_PLATFORM_ANDROID, native_display,
+                          attrib_list);
+}
+#endif /* HAVE_ANDROID_PLATFORM */
+
+_EGLDisplay*
+_eglGetDeviceDisplay(void *native_display,
+                     const EGLAttrib *attrib_list)
+{
+   _EGLDevice *dev;
+   _EGLDisplay *display;
+   int fd = -1;
+
+   dev = _eglLookupDevice(native_display);
+   if (!dev) {
+      _eglError(EGL_BAD_PARAMETER, "eglGetPlatformDisplay");
+      return NULL;
+   }
+
+   if (attrib_list) {
+      for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+         EGLAttrib attrib = attrib_list[i];
+         EGLAttrib value = attrib_list[i + 1];
+
+         /* EGL_EXT_platform_device does not recognize any attributes,
+          * EGL_EXT_device_drm adds the optional EGL_DRM_MASTER_FD_EXT.
+          */
+
+         if (!_eglDeviceSupports(dev, _EGL_DEVICE_DRM) ||
+             attrib != EGL_DRM_MASTER_FD_EXT) {
+            _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+            return NULL;
+         }
+
+         fd = (int) value;
+      }
+   }
+
+   display = _eglFindDisplay(_EGL_PLATFORM_DEVICE, native_display, attrib_list);
+   if (!display) {
+      _eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
+      return NULL;
+   }
+
+   /* If the fd is explicitly provided and we did not dup() it yet, do so.
+    * The spec mandates that we do so, since we'll need it past the
+    * eglGetPlatformDispay call.
+    *
+    * The new fd is guaranteed to be 3 or greater.
+    */
+   if (fd != -1 && display->Options.fd == 0) {
+      display->Options.fd = os_dupfd_cloexec(fd);
+      if (display->Options.fd == -1) {
+         /* Do not (really) need to teardown the display */
+         _eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
+         return NULL;
+      }
+   }
+
+   return display;
+}