egl: Native Display autodetection
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?) Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
This commit is contained in:
@@ -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
|
||||
|
@@ -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)\"
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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.
|
||||
@@ -83,18 +100,95 @@ _eglGetNativePlatformFromEnv(void)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform validity checks on a generic pointer.
|
||||
*/
|
||||
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;
|
||||
|
@@ -150,7 +150,7 @@ struct _egl_display
|
||||
|
||||
|
||||
extern _EGLPlatformType
|
||||
_eglGetNativePlatform(void);
|
||||
_eglGetNativePlatform(EGLNativeDisplayType nativeDisplay);
|
||||
|
||||
|
||||
extern void
|
||||
|
Reference in New Issue
Block a user