diff options
author | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-08-09 14:23:18 +0200 |
---|---|---|
committer | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-08-15 09:42:16 +0200 |
commit | 85fe9484945cb57ffd49df248b0e5057eba6af04 (patch) | |
tree | c41d0a8191d087b1b3c1d0d274929fb7f8b376a5 | |
parent | f5e757ea60d9abb848d98af01e1986be3e35e236 (diff) |
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>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/egl/main/Makefile | 13 | ||||
-rw-r--r-- | src/egl/main/eglapi.c | 8 | ||||
-rw-r--r-- | src/egl/main/egldisplay.c | 100 | ||||
-rw-r--r-- | src/egl/main/egldisplay.h | 2 |
5 files changed, 117 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac index 1b1823a211f..9195da9b3a3 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -1370,6 +1370,8 @@ if test "x$enable_egl" = xyes; then | |||
1370 | EGL_LIB_DEPS="$DLOPEN_LIBS $SELINUX_LIBS -lpthread" | 1370 | EGL_LIB_DEPS="$DLOPEN_LIBS $SELINUX_LIBS -lpthread" |
1371 | EGL_DRIVERS_DIRS="" | 1371 | EGL_DRIVERS_DIRS="" |
1372 | 1372 | ||
1373 | AC_CHECK_FUNC(mincore, [DEFINES="$DEFINES -DHAVE_MINCORE"]) | ||
1374 | |||
1373 | if test "$enable_static" != yes; then | 1375 | if test "$enable_static" != yes; then |
1374 | # build egl_glx when libGL is built | 1376 | # build egl_glx when libGL is built |
1375 | if test "x$enable_glx" = xyes; then | 1377 | if test "x$enable_glx" = xyes; then |
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index 775fbbe178b..c100fbfeb9c 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile | |||
@@ -93,6 +93,19 @@ ifeq ($(firstword $(EGL_PLATFORMS)),fbdev) | |||
93 | EGL_NATIVE_PLATFORM=_EGL_PLATFORM_FBDEV | 93 | EGL_NATIVE_PLATFORM=_EGL_PLATFORM_FBDEV |
94 | endif | 94 | endif |
95 | 95 | ||
96 | ifneq ($(findstring x11, $(EGL_PLATFORMS)),) | ||
97 | LOCAL_CFLAGS += -DHAVE_X11_PLATFORM | ||
98 | endif | ||
99 | ifneq ($(findstring wayland, $(EGL_PLATFORMS)),) | ||
100 | LOCAL_CFLAGS += -DHAVE_WAYLAND_PLATFORM | ||
101 | endif | ||
102 | ifneq ($(findstring drm, $(EGL_PLATFORMS)),) | ||
103 | LOCAL_CFLAGS += -DHAVE_DRM_PLATFORM | ||
104 | endif | ||
105 | ifneq ($(findstring fbdev, $(EGL_PLATFORMS)),) | ||
106 | LOCAL_CFLAGS += -DHAVE_FBDEV_PLATFORM | ||
107 | endif | ||
108 | |||
96 | LOCAL_CFLAGS += \ | 109 | LOCAL_CFLAGS += \ |
97 | -D_EGL_NATIVE_PLATFORM=$(EGL_NATIVE_PLATFORM) \ | 110 | -D_EGL_NATIVE_PLATFORM=$(EGL_NATIVE_PLATFORM) \ |
98 | -D_EGL_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\" | 111 | -D_EGL_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\" |
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 0ba7794e2c9..5d186c60e5a 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c | |||
@@ -301,7 +301,7 @@ _eglUnlockDisplay(_EGLDisplay *dpy) | |||
301 | EGLDisplay EGLAPIENTRY | 301 | EGLDisplay EGLAPIENTRY |
302 | eglGetDisplay(EGLNativeDisplayType nativeDisplay) | 302 | eglGetDisplay(EGLNativeDisplayType nativeDisplay) |
303 | { | 303 | { |
304 | _EGLPlatformType plat = _eglGetNativePlatform(); | 304 | _EGLPlatformType plat = _eglGetNativePlatform(nativeDisplay); |
305 | _EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay); | 305 | _EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay); |
306 | return _eglGetDisplayHandle(dpy); | 306 | return _eglGetDisplayHandle(dpy); |
307 | } | 307 | } |
@@ -538,7 +538,7 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, | |||
538 | EGLSurface ret; | 538 | EGLSurface ret; |
539 | 539 | ||
540 | _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); | 540 | _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); |
541 | if (disp->Platform != _eglGetNativePlatform()) | 541 | if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay)) |
542 | RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); | 542 | RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); |
543 | 543 | ||
544 | surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list); | 544 | surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list); |
@@ -559,7 +559,7 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, | |||
559 | EGLSurface ret; | 559 | EGLSurface ret; |
560 | 560 | ||
561 | _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); | 561 | _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); |
562 | if (disp->Platform != _eglGetNativePlatform()) | 562 | if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay)) |
563 | RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); | 563 | RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); |
564 | 564 | ||
565 | surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list); | 565 | surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list); |
@@ -720,7 +720,7 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) | |||
720 | EGLBoolean ret; | 720 | EGLBoolean ret; |
721 | 721 | ||
722 | _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); | 722 | _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); |
723 | if (disp->Platform != _eglGetNativePlatform()) | 723 | if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay)) |
724 | RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE); | 724 | RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE); |
725 | ret = drv->API.CopyBuffers(drv, disp, surf, target); | 725 | ret = drv->API.CopyBuffers(drv, disp, surf, target); |
726 | 726 | ||
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 60f31777272..2849dd96c64 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c | |||
@@ -43,6 +43,23 @@ | |||
43 | #include "eglmutex.h" | 43 | #include "eglmutex.h" |
44 | #include "egllog.h" | 44 | #include "egllog.h" |
45 | 45 | ||
46 | /* Includes for _eglNativePlatformDetectNativeDisplay */ | ||
47 | #ifdef HAVE_MINCORE | ||
48 | #include <unistd.h> | ||
49 | #include <sys/mman.h> | ||
50 | #endif | ||
51 | #ifdef HAVE_WAYLAND_PLATFORM | ||
52 | #include <wayland-client.h> | ||
53 | #endif | ||
54 | #ifdef HAVE_DRM_PLATFORM | ||
55 | #include <gbm.h> | ||
56 | #endif | ||
57 | #ifdef HAVE_FBDEV_PLATFORM | ||
58 | #include <stdint.h> | ||
59 | #include <sys/types.h> | ||
60 | #include <sys/stat.h> | ||
61 | #endif | ||
62 | |||
46 | 63 | ||
47 | /** | 64 | /** |
48 | * Return the native platform by parsing EGL_PLATFORM. | 65 | * Return the native platform by parsing EGL_PLATFORM. |
@@ -84,17 +101,94 @@ _eglGetNativePlatformFromEnv(void) | |||
84 | 101 | ||
85 | 102 | ||
86 | /** | 103 | /** |
104 | * Perform validity checks on a generic pointer. | ||
105 | */ | ||
106 | static EGLBoolean | ||
107 | _eglPointerIsDereferencable(void *p) | ||
108 | { | ||
109 | #ifdef HAVE_MINCORE | ||
110 | uintptr_t addr = (uintptr_t) p; | ||
111 | unsigned char valid = 0; | ||
112 | const long page_size = getpagesize(); | ||
113 | |||
114 | if (p == NULL) | ||
115 | return EGL_FALSE; | ||
116 | |||
117 | /* align addr to page_size */ | ||
118 | addr &= ~(page_size - 1); | ||
119 | |||
120 | if (mincore((void *) addr, page_size, &valid) < 0) { | ||
121 | _eglLog(_EGL_DEBUG, "mincore failed: %m"); | ||
122 | return EGL_FALSE; | ||
123 | } | ||
124 | |||
125 | return (valid & 0x01) == 0x01; | ||
126 | #else | ||
127 | return p != NULL; | ||
128 | #endif | ||
129 | } | ||
130 | |||
131 | |||
132 | /** | ||
133 | * Try detecting native platform with the help of native display characteristcs. | ||
134 | */ | ||
135 | static _EGLPlatformType | ||
136 | _eglNativePlatformDetectNativeDisplay(EGLNativeDisplayType nativeDisplay) | ||
137 | { | ||
138 | #ifdef HAVE_FBDEV_PLATFORM | ||
139 | struct stat buf; | ||
140 | #endif | ||
141 | |||
142 | if (nativeDisplay == EGL_DEFAULT_DISPLAY) | ||
143 | return _EGL_INVALID_PLATFORM; | ||
144 | |||
145 | #ifdef HAVE_FBDEV_PLATFORM | ||
146 | /* fbdev is the only platform that can be a file descriptor. */ | ||
147 | if (fstat((intptr_t) nativeDisplay, &buf) == 0 && S_ISCHR(buf.st_mode)) | ||
148 | return _EGL_PLATFORM_FBDEV; | ||
149 | #endif | ||
150 | |||
151 | if (_eglPointerIsDereferencable(nativeDisplay)) { | ||
152 | void *first_pointer = *(void **) nativeDisplay; | ||
153 | |||
154 | #ifdef HAVE_WAYLAND_PLATFORM | ||
155 | /* wl_display is a wl_proxy, which is a wl_object. | ||
156 | * wl_object's first element points to the interfacetype. */ | ||
157 | if (first_pointer == &wl_display_interface) | ||
158 | return _EGL_PLATFORM_WAYLAND; | ||
159 | #endif | ||
160 | |||
161 | #ifdef HAVE_DRM_PLATFORM | ||
162 | /* gbm has a pointer to its constructor as first element. */ | ||
163 | if (first_pointer == gbm_create_device) | ||
164 | return _EGL_PLATFORM_DRM; | ||
165 | #endif | ||
166 | |||
167 | #ifdef HAVE_X11_PLATFORM | ||
168 | /* If not matched to any other platform, fallback to x11. */ | ||
169 | return _EGL_PLATFORM_X11; | ||
170 | #endif | ||
171 | } | ||
172 | |||
173 | return _EGL_INVALID_PLATFORM; | ||
174 | } | ||
175 | |||
176 | |||
177 | /** | ||
87 | * Return the native platform. It is the platform of the EGL native types. | 178 | * Return the native platform. It is the platform of the EGL native types. |
88 | */ | 179 | */ |
89 | _EGLPlatformType | 180 | _EGLPlatformType |
90 | _eglGetNativePlatform(void) | 181 | _eglGetNativePlatform(EGLNativeDisplayType nativeDisplay) |
91 | { | 182 | { |
92 | static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM; | 183 | static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM; |
93 | 184 | ||
94 | if (native_platform == _EGL_INVALID_PLATFORM) { | 185 | if (native_platform == _EGL_INVALID_PLATFORM) { |
95 | native_platform = _eglGetNativePlatformFromEnv(); | 186 | native_platform = _eglGetNativePlatformFromEnv(); |
96 | if (native_platform == _EGL_INVALID_PLATFORM) | 187 | if (native_platform == _EGL_INVALID_PLATFORM) { |
97 | native_platform = _EGL_NATIVE_PLATFORM; | 188 | native_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay); |
189 | if (native_platform == _EGL_INVALID_PLATFORM) | ||
190 | native_platform = _EGL_NATIVE_PLATFORM; | ||
191 | } | ||
98 | } | 192 | } |
99 | 193 | ||
100 | return native_platform; | 194 | return native_platform; |
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 9cd4dbfcc8a..05335ada63c 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h | |||
@@ -150,7 +150,7 @@ struct _egl_display | |||
150 | 150 | ||
151 | 151 | ||
152 | extern _EGLPlatformType | 152 | extern _EGLPlatformType |
153 | _eglGetNativePlatform(void); | 153 | _eglGetNativePlatform(EGLNativeDisplayType nativeDisplay); |
154 | 154 | ||
155 | 155 | ||
156 | extern void | 156 | extern void |