mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-21 11:30:11 +01:00
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:
parent
f5e757ea60
commit
85fe948494
5 changed files with 117 additions and 8 deletions
|
|
@ -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,19 +100,96 @@ _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 = _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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue