egl/main: Enable Linux platform extensions
authorChad Versace <chad.versace@linux.intel.com>
Thu, 23 Jan 2014 15:26:10 +0000 (07:26 -0800)
committerChad Versace <chad.versace@linux.intel.com>
Mon, 17 Mar 2014 22:49:06 +0000 (15:49 -0700)
Enable EGL_EXT_platform_base and the Linux platform extensions layered
atop it: EGL_EXT_platform_x11, EGL_EXT_platform_wayland,
and EGL_MESA_platform_gbm.

Tested with Piglit's EGL_EXT_platform_base tests under an X11 session.
To enable running the Wayland and GBM tests, windowed Weston was running
and the kernel had render nodes enabled.

I regression tested my EGL_EXT_platform_base patch set with Piglit on
Ivybridge under X11/EGL, standalone Weston, and GBM with rendernodes. No
regressions found.

Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
src/egl/main/eglapi.c
src/egl/main/egldisplay.c
src/egl/main/egldisplay.h
src/egl/main/eglglobals.c
src/egl/main/eglglobals.h

index 836714ce244342e8932c1700b033cba107706906..219d8e61715551061187bb334e93ad72ed7d9cfa 100644 (file)
@@ -308,6 +308,36 @@ eglGetDisplay(EGLNativeDisplayType nativeDisplay)
    return _eglGetDisplayHandle(dpy);
 }
 
+EGLDisplay EGLAPIENTRY
+eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
+                         const EGLint *attrib_list)
+{
+   _EGLDisplay *dpy;
+
+   switch (platform) {
+#ifdef HAVE_X11_PLATFORM
+   case EGL_PLATFORM_X11_EXT:
+      dpy = _eglGetX11Display((Display*) native_display, attrib_list);
+      break;
+#endif
+#ifdef HAVE_DRM_PLATFORM
+   case EGL_PLATFORM_GBM_MESA:
+      dpy = _eglGetGbmDisplay((struct gbm_device*) native_display,
+                              attrib_list);
+      break;
+#endif
+#ifdef HAVE_WAYLAND_PLATFORM
+   case EGL_PLATFORM_WAYLAND_EXT:
+      dpy = _eglGetWaylandDisplay((struct wl_display*) native_display,
+                                  attrib_list);
+      break;
+#endif
+   default:
+      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
+   }
+
+   return _eglGetDisplayHandle(dpy);
+}
 
 /**
  * This is typically the second EGL function that an application calls.
@@ -527,25 +557,17 @@ eglQueryContext(EGLDisplay dpy, EGLContext ctx,
 }
 
 
-EGLSurface EGLAPIENTRY
-eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
-                       EGLNativeWindowType window, const EGLint *attrib_list)
+static EGLSurface
+_eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
+                              void *native_window, const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
    EGLSurface ret;
-   void *native_window_ptr;
-
-   STATIC_ASSERT(sizeof(void*) == sizeof(window));
-   native_window_ptr = (void*) window;
 
    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
-   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
-      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
-
-   surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window_ptr,
+   surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
                                        attrib_list);
    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
 
@@ -554,24 +576,52 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
 
 
 EGLSurface EGLAPIENTRY
-eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
-                       EGLNativePixmapType pixmap, const EGLint *attrib_list)
+eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
+                       EGLNativeWindowType window, const EGLint *attrib_list)
 {
    _EGLDisplay *disp = _eglLockDisplay(dpy);
+   STATIC_ASSERT(sizeof(void*) == sizeof(window));
+   return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
+                                        attrib_list);
+}
+
+
+EGLSurface EGLAPIENTRY
+eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
+                                  void *native_window,
+                                  const EGLint *attrib_list)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+
+#ifdef HAVE_X11_PLATFORM
+   if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
+      /* The `native_window` parameter for the X11 platform differs between
+       * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
+       * eglCreateWindowSurface(), the type of `native_window` is an Xlib
+       * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
+       * `Window*`.  Convert `Window*` to `Window` because that's what
+       * dri2_x11_create_window_surface() expects.
+       */
+      native_window = (void*) (* (Window*) native_window);
+   }
+#endif
+
+   return _eglCreateWindowSurfaceCommon(disp, config, native_window,
+                                        attrib_list);
+}
+
+
+static EGLSurface
+_eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
+                              void *native_pixmap, const EGLint *attrib_list)
+{
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
    EGLSurface ret;
-   void *native_pixmap_ptr;
-
-   STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
-   native_pixmap_ptr = (void*) pixmap;
 
    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
-   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
-      RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
-
-   surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap_ptr,
+   surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
                                        attrib_list);
    ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
 
@@ -579,6 +629,41 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
 }
 
 
+EGLSurface EGLAPIENTRY
+eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
+                       EGLNativePixmapType pixmap, const EGLint *attrib_list)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
+   return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
+                                         attrib_list);
+}
+
+EGLSurface EGLAPIENTRY
+eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
+                                   void *native_pixmap,
+                                   const EGLint *attrib_list)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+
+#ifdef HAVE_X11_PLATFORM
+      /* The `native_pixmap` parameter for the X11 platform differs between
+       * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
+       * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
+       * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
+       * `Pixmap*`.  Convert `Pixmap*` to `Pixmap` because that's what
+       * dri2_x11_create_pixmap_surface() expects.
+       */
+   if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) {
+      native_pixmap = (void*) (* (Pixmap*) native_pixmap);
+   }
+#endif
+
+   return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
+                                        attrib_list);
+}
+
+
 EGLSurface EGLAPIENTRY
 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
                         const EGLint *attrib_list)
@@ -998,6 +1083,9 @@ eglGetProcAddress(const char *procname)
 #ifdef EGL_EXT_swap_buffers_with_damage
       { "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT },
 #endif
+      { "eglGetPlatformDisplayEXT", (_EGLProc) eglGetPlatformDisplayEXT },
+      { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT },
+      { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT },
       { NULL, NULL }
    };
    EGLint i;
index b43e3ea5d9b2d5dd46bff4bb439c701dc2cf3a80..76dfee72ab7217cfc70145245db333c65064bf48 100644 (file)
@@ -36,6 +36,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "eglcontext.h"
+#include "eglcurrent.h"
 #include "eglsurface.h"
 #include "egldisplay.h"
 #include "egldriver.h"
@@ -458,3 +459,74 @@ _eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
    /* We always unlink before destroy.  The driver still owns a reference */
    assert(res->RefCount);
 }
+
+#ifdef HAVE_X11_PLATFORM
+static EGLBoolean
+_eglParseX11DisplayAttribList(const EGLint *attrib_list)
+{
+   int i;
+
+   if (attrib_list == NULL) {
+      return EGL_TRUE;
+   }
+
+   for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+      EGLint attrib = attrib_list[i];
+      EGLint value = attrib_list[i + 1];
+
+      /* EGL_EXT_platform_x11 recognizes exactly one attribute,
+       * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
+       * 
+       * Mesa supports connecting to only the default screen, so we reject
+       * screen != 0.
+       */
+      if (attrib != EGL_PLATFORM_X11_SCREEN_EXT || value != 0) {
+         _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+         return EGL_FALSE;
+      }
+   }
+
+   return EGL_TRUE;
+}
+
+_EGLDisplay*
+_eglGetX11Display(Display *native_display,
+                  const EGLint *attrib_list)
+{
+   if (!_eglParseX11DisplayAttribList(attrib_list)) {
+      return NULL;
+   }
+
+   return _eglFindDisplay(_EGL_PLATFORM_X11, native_display);
+}
+#endif /* HAVE_X11_PLATFORM */
+
+#ifdef HAVE_DRM_PLATFORM
+_EGLDisplay*
+_eglGetGbmDisplay(struct gbm_device *native_display,
+                  const EGLint *attrib_list)
+{
+   /* EGL_MESA_platform_gbm recognizes no attributes. */
+   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
+      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+      return NULL;
+   }
+
+   return _eglFindDisplay(_EGL_PLATFORM_DRM, native_display);
+}
+#endif /* HAVE_DRM_PLATFORM */
+
+#ifdef HAVE_WAYLAND_PLATFORM
+_EGLDisplay*
+_eglGetWaylandDisplay(struct wl_display *native_display,
+                      const EGLint *attrib_list)
+{
+   /* EGL_EXT_platform_wayland recognizes no attributes. */
+   if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
+      _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+      return NULL;
+   }
+
+   return _eglFindDisplay(_EGL_PLATFORM_WAYLAND, native_display);
+}
+#endif /* HAVE_WAYLAND_PLATFORM */
index 911a2e9bd67a47a1a9936a51c94286c5606d2ef0..970c21a9289a3e6c4c4d1bf077f2cf94f1b05121 100644 (file)
@@ -242,5 +242,25 @@ _eglIsResourceLinked(_EGLResource *res)
    return res->IsLinked;
 }
 
+#ifdef HAVE_X11_PLATFORM
+_EGLDisplay*
+_eglGetX11Display(Display *native_display, const EGLint *attrib_list);
+#endif
+
+#ifdef HAVE_DRM_PLATFORM
+struct gbm_device;
+
+_EGLDisplay*
+_eglGetGbmDisplay(struct gbm_device *native_display,
+                  const EGLint *attrib_list);
+#endif
+
+#ifdef HAVE_WAYLAND_PLATFORM
+struct wl_display;
+
+_EGLDisplay*
+_eglGetWaylandDisplay(struct wl_display *native_display,
+                      const EGLint *attrib_list);
+#endif
 
 #endif /* EGLDISPLAY_INCLUDED */
index 956fa9199f21afbdd044367d69f976b5e43f8de3..cf669cff681cbd33bf4ad2ab40af1b6e4706259c 100644 (file)
@@ -51,11 +51,19 @@ struct _egl_global _eglGlobal =
 
    /* ClientExtensions */
    {
-      true /* EGL_EXT_client_extensions */
+      true, /* EGL_EXT_client_extensions */
+      true, /* EGL_EXT_platform_base */
+      true, /* EGL_EXT_platform_x11 */
+      true, /* EGL_EXT_platform_wayland */
+      true  /* EGL_MESA_platform_gbm */
    },
 
    /* ClientExtensionsString */
    "EGL_EXT_client_extensions"
+   " EGL_EXT_platform_base"
+   " EGL_EXT_platform_x11"
+   " EGL_EXT_platform_wayland"
+   " EGL_MESA_platform_gbm"
 };
 
 
index 5ec6769a8e1141cb8c090593e549af4f2c01bc2b..9046ea25c3c6f6f8e51e7eec8accd13a8d175e7c 100644 (file)
@@ -52,6 +52,10 @@ struct _egl_global
 
    struct _egl_client_extensions {
       bool EXT_client_extensions;
+      bool EXT_platform_base;
+      bool EXT_platform_x11;
+      bool EXT_platform_wayland;
+      bool MESA_platform_gbm;
    } ClientExtensions;
 
    const char *ClientExtensionString;