[Mesa-dev] [PATCH 1/3][RFC] egl: Native Display autodetection

Chia-I Wu olvaffe at gmail.com
Tue Aug 9 20:13:39 PDT 2011


On Tue, Aug 9, 2011 at 10:53 PM, Benjamin Franzke
<benjaminfranzke at googlemail.com> wrote:
> EGL doesnt define howto manage different native platforms.
> So mesa has a builtime configurable default platform,
> whith non-standard envvar (EGL_PLATFORM) overwrites.
> This caused unneeded bugreports, when EGL_PLATFORM was forgotten.
>
> Detection is grouped into basic types of NativeDisplays (which itself
> needs to be detected).  The final decision is based on characteristcs
> of these basic types:
>
>  File Desciptor based platforms (fbdev):
>    - fstat(2) to check for being a fd that belongs to a character device
>    - check kernel subsystem (todo)
>
>  Pointer to structuctures (x11, wayland, drm/gbm):
>    - mincore(2) to check whether its valid pointer to some memory.
>    - magic elements (e.g. pointers to exported symbols):
>      o wayland display stores interface type pointer (first elm.)
>      o gbm stores pointer to its constructor (first elm.)
>      o x11 as a fallback (FIXME?)
The first and third patches look good to me.  But the second patch
seems like an extension to EGL to me.  How is it useful in practice
and how can the spec be updated?


> Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>
> ---
>  configure.ac              |    2 +
>  src/egl/main/Makefile     |   13 ++++++
>  src/egl/main/eglapi.c     |    8 ++--
>  src/egl/main/egldisplay.c |   95 +++++++++++++++++++++++++++++++++++++++++++-
>  src/egl/main/egldisplay.h |    2 +-
>  5 files changed, 112 insertions(+), 8 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 1b1823a..9195da9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1370,6 +1370,8 @@ if test "x$enable_egl" = xyes; then
>     EGL_LIB_DEPS="$DLOPEN_LIBS $SELINUX_LIBS -lpthread"
>     EGL_DRIVERS_DIRS=""
>
> +    AC_CHECK_FUNC(mincore, [DEFINES="$DEFINES -DHAVE_MINCORE"])
> +
>     if test "$enable_static" != yes; then
>         # build egl_glx when libGL is built
>         if test "x$enable_glx" = xyes; then
> diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
> index 775fbbe..c100fbf 100644
> --- a/src/egl/main/Makefile
> +++ b/src/egl/main/Makefile
> @@ -93,6 +93,19 @@ ifeq ($(firstword $(EGL_PLATFORMS)),fbdev)
>  EGL_NATIVE_PLATFORM=_EGL_PLATFORM_FBDEV
>  endif
>
> +ifneq ($(findstring x11, $(EGL_PLATFORMS)),)
> +LOCAL_CFLAGS += -DHAVE_X11_PLATFORM
> +endif
> +ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
> +LOCAL_CFLAGS += -DHAVE_WAYLAND_PLATFORM
> +endif
> +ifneq ($(findstring drm, $(EGL_PLATFORMS)),)
> +LOCAL_CFLAGS += -DHAVE_DRM_PLATFORM
> +endif
> +ifneq ($(findstring fbdev, $(EGL_PLATFORMS)),)
> +LOCAL_CFLAGS += -DHAVE_FBDEV_PLATFORM
> +endif
> +
>  LOCAL_CFLAGS += \
>        -D_EGL_NATIVE_PLATFORM=$(EGL_NATIVE_PLATFORM) \
>        -D_EGL_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\"
> diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
> index 0ba7794..5d186c6 100644
> --- a/src/egl/main/eglapi.c
> +++ b/src/egl/main/eglapi.c
> @@ -301,7 +301,7 @@ _eglUnlockDisplay(_EGLDisplay *dpy)
>  EGLDisplay EGLAPIENTRY
>  eglGetDisplay(EGLNativeDisplayType nativeDisplay)
>  {
> -   _EGLPlatformType plat = _eglGetNativePlatform();
> +   _EGLPlatformType plat = _eglGetNativePlatform(nativeDisplay);
>    _EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay);
>    return _eglGetDisplayHandle(dpy);
>  }
> @@ -538,7 +538,7 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
>    EGLSurface ret;
>
>    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
> -   if (disp->Platform != _eglGetNativePlatform())
> +   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
>       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
>
>    surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
> @@ -559,7 +559,7 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
>    EGLSurface ret;
>
>    _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
> -   if (disp->Platform != _eglGetNativePlatform())
> +   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
>       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
>
>    surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
> @@ -720,7 +720,7 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
>    EGLBoolean ret;
>
>    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
> -   if (disp->Platform != _eglGetNativePlatform())
> +   if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
>       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
>    ret = drv->API.CopyBuffers(drv, disp, surf, target);
>
> diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
> index 60f3177..bd4fe19 100644
> --- a/src/egl/main/egldisplay.c
> +++ b/src/egl/main/egldisplay.c
> @@ -43,6 +43,23 @@
>  #include "eglmutex.h"
>  #include "egllog.h"
>
> +/* Includes for _eglNativePlatformDetectNativeDisplay */
> +#ifdef HAVE_MINCORE
> +#include <unistd.h>
> +#include <sys/mman.h>
> +#endif
> +#ifdef HAVE_WAYLAND_PLATFORM
> +#include <wayland-client.h>
> +#endif
> +#ifdef HAVE_DRM_PLATFORM
> +#include <gbm.h>
> +#endif
> +#ifdef HAVE_FBDEV_PLATFORM
> +#include <stdint.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#endif
> +
>
>  /**
>  * Return the native platform by parsing EGL_PLATFORM.
> @@ -82,19 +99,91 @@ _eglGetNativePlatformFromEnv(void)
>    return plat;
>  }
>
> +static EGLBoolean
> +_eglPointerIsDereferencable(void *p)
> +{
> +#ifdef HAVE_MINCORE
> +   uintptr_t addr = (uintptr_t) p;
> +   unsigned char valid = 0;
> +   const long page_size = getpagesize();
> +
> +   if (p == NULL)
> +      return EGL_FALSE;
> +
> +   /* align addr to page_size */
> +   addr &= ~(page_size - 1);
> +
> +   if (mincore((void *) addr, page_size, &valid) < 0) {
> +      _eglLog(_EGL_DEBUG, "mincore failed: %m");
> +      return EGL_FALSE;
> +   }
> +
> +   return (valid & 0x01) == 0x01;
> +#else
> +   return p != NULL;
> +#endif
> +}
> +
> +/**
> + * Try detecting native platform with the help of native display characteristcs.
> + */
> +static _EGLPlatformType
> +_eglNativePlatformDetectNativeDisplay(EGLNativeDisplayType nativeDisplay)
> +{
> +#ifdef HAVE_FBDEV_PLATFORM
> +   struct stat buf;
> +#endif
> +
> +   if (nativeDisplay == EGL_DEFAULT_DISPLAY)
> +      return _EGL_INVALID_PLATFORM;
> +
> +#ifdef HAVE_FBDEV_PLATFORM
> +   /* fbdev is the only platform that can be a file descriptor. */
> +   if (fstat((intptr_t) nativeDisplay, &buf) == 0 && S_ISCHR(buf.st_mode))
> +      return _EGL_PLATFORM_FBDEV;
> +#endif
> +
> +   if (_eglPointerIsDereferencable(nativeDisplay)) {
> +      void *first_pointer = *(void **) nativeDisplay;
> +
> +#ifdef HAVE_WAYLAND_PLATFORM
> +      /* wl_display is a wl_proxy, which is a wl_object.
> +       * wl_object's first element points to the interfacetype. */
> +      if (first_pointer == &wl_display_interface)
> +         return _EGL_PLATFORM_WAYLAND;
> +#endif
> +
> +#ifdef HAVE_DRM_PLATFORM
> +      /* gbm has a pointer to its constructor as first element. */
> +      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
> +   }
> +
> +   return _EGL_INVALID_PLATFORM;
> +}
> +
>
>  /**
>  * Return the native platform.  It is the platform of the EGL native types.
>  */
>  _EGLPlatformType
> -_eglGetNativePlatform(void)
> +_eglGetNativePlatform(EGLNativeDisplayType nativeDisplay)
>  {
>    static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
>
>    if (native_platform == _EGL_INVALID_PLATFORM) {
>       native_platform = _eglGetNativePlatformFromEnv();
> -      if (native_platform == _EGL_INVALID_PLATFORM)
> -         native_platform = _EGL_NATIVE_PLATFORM;
> +      if (native_platform == _EGL_INVALID_PLATFORM) {
> +         native_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
> +         if (native_platform == _EGL_INVALID_PLATFORM)
> +            native_platform = _EGL_NATIVE_PLATFORM;
> +      }
>    }
>
>    return native_platform;
> diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
> index 9cd4dbf..05335ad 100644
> --- a/src/egl/main/egldisplay.h
> +++ b/src/egl/main/egldisplay.h
> @@ -150,7 +150,7 @@ struct _egl_display
>
>
>  extern _EGLPlatformType
> -_eglGetNativePlatform(void);
> +_eglGetNativePlatform(EGLNativeDisplayType nativeDisplay);
>
>
>  extern void
> --
> 1.7.3.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>



-- 
olv at LunarG.com


More information about the mesa-dev mailing list