From 468cc866b4b308cee40470f06b31002c6c56da96 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 23 Jan 2014 07:26:10 -0800 Subject: [PATCH] egl/main: Enable Linux platform extensions 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 --- src/egl/main/eglapi.c | 132 +++++++++++++++++++++++++++++++------- src/egl/main/egldisplay.c | 72 +++++++++++++++++++++ src/egl/main/egldisplay.h | 20 ++++++ src/egl/main/eglglobals.c | 10 ++- src/egl/main/eglglobals.h | 4 ++ 5 files changed, 215 insertions(+), 23 deletions(-) diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 836714ce244..219d8e61715 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -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; diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index b43e3ea5d9b..76dfee72ab7 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -36,6 +36,7 @@ #include #include #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 */ diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 911a2e9bd67..970c21a9289 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -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 */ diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index 956fa9199f2..cf669cff681 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -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" }; diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index 5ec6769a8e1..9046ea25c3c 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -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; -- 2.30.2