#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
#include "c11/threads.h"
+#include "util/macros.h"
#include "util/u_atomic.h"
#include "eglcontext.h"
#include "eglcurrent.h"
#include "eglsurface.h"
+#include "egldevice.h"
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
static const struct {
_EGLPlatformType platform;
const char *name;
-} egl_platforms[_EGL_NUM_PLATFORMS] = {
+} egl_platforms[] = {
{ _EGL_PLATFORM_X11, "x11" },
{ _EGL_PLATFORM_WAYLAND, "wayland" },
{ _EGL_PLATFORM_DRM, "drm" },
{ _EGL_PLATFORM_ANDROID, "android" },
{ _EGL_PLATFORM_HAIKU, "haiku" },
{ _EGL_PLATFORM_SURFACELESS, "surfaceless" },
+ { _EGL_PLATFORM_DEVICE, "device" },
};
const char *plat_name;
EGLint i;
+ static_assert(ARRAY_SIZE(egl_platforms) == _EGL_NUM_PLATFORMS,
+ "Missing platform");
+
plat_name = getenv("EGL_PLATFORM");
/* try deprecated env variable */
if (!plat_name || !plat_name[0])
if (!plat_name || !plat_name[0])
return _EGL_INVALID_PLATFORM;
- for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
+ for (i = 0; i < ARRAY_SIZE(egl_platforms); i++) {
if (strcmp(egl_platforms[i].name, plat_name) == 0) {
plat = egl_platforms[i].platform;
break;
}
}
+ if (plat == _EGL_INVALID_PLATFORM)
+ _eglLog(_EGL_WARNING, "invalid EGL_PLATFORM given");
+
return plat;
}
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
-
-#ifdef HAVE_HAIKU_PLATFORM
- return _EGL_PLATFORM_HAIKU;
-#endif
}
return _EGL_INVALID_PLATFORM;
_EGLPlatformType
_eglGetNativePlatform(void *nativeDisplay)
{
- static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
- _EGLPlatformType detected_platform = native_platform;
+ _EGLPlatformType detected_platform = _eglGetNativePlatformFromEnv();
+ const char *detection_method = "environment";
if (detected_platform == _EGL_INVALID_PLATFORM) {
- const char *detection_method;
-
- detected_platform = _eglGetNativePlatformFromEnv();
- detection_method = "environment overwrite";
-
- if (detected_platform == _EGL_INVALID_PLATFORM) {
- detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
- detection_method = "autodetected";
- }
-
- if (detected_platform == _EGL_INVALID_PLATFORM) {
- detected_platform = _EGL_NATIVE_PLATFORM;
- detection_method = "build-time configuration";
- }
-
- _eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
- egl_platforms[detected_platform].name, detection_method);
+ detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
+ detection_method = "autodetected";
+ }
- p_atomic_cmpxchg(&native_platform, _EGL_INVALID_PLATFORM,
- detected_platform);
+ if (detected_platform == _EGL_INVALID_PLATFORM) {
+ detected_platform = _EGL_NATIVE_PLATFORM;
+ detection_method = "build-time configuration";
}
- return native_platform;
+ _eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
+ egl_platforms[detected_platform].name, detection_method);
+
+ return detected_platform;
}
}
}
+
+ /* The fcntl() code in _eglGetDeviceDisplay() ensures that valid fd >= 3,
+ * and invalid one is 0.
+ */
+ if (disp->Options.fd)
+ close(disp->Options.fd);
+
free(disp->Options.Attribs);
free(disp);
}
return EGL_TRUE;
/* otherwise, compare the lists */
- return memcmp(a, b, na) == 0 ? EGL_TRUE : EGL_FALSE;
+ return memcmp(a, b, na * sizeof(a[0])) == 0 ? EGL_TRUE : EGL_FALSE;
}
/**
mtx_lock(_eglGlobal.Mutex);
/* search the display list first */
- disp = _eglGlobal.DisplayList;
- while (disp) {
+ for (disp = _eglGlobal.DisplayList; disp; disp = disp->Next) {
if (disp->Platform == plat && disp->PlatformDisplay == plat_dpy &&
_eglSameAttribs(disp->Options.Attribs, attrib_list))
break;
- disp = disp->Next;
}
/* create a new display */
}
#ifdef HAVE_X11_PLATFORM
-static EGLBoolean
-_eglParseX11DisplayAttribList(_EGLDisplay *display,
- const EGLAttrib *attrib_list)
-{
- int i;
-
- if (attrib_list == NULL) {
- return EGL_TRUE;
- }
-
- /* EGL_EXT_platform_x11 recognizes exactly one attribute,
- * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
- */
- for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
- if (attrib_list[i] != EGL_PLATFORM_X11_SCREEN_EXT)
- return _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
- }
-
- return EGL_TRUE;
-}
-
_EGLDisplay*
_eglGetX11Display(Display *native_display,
const EGLAttrib *attrib_list)
{
- _EGLDisplay *display = _eglFindDisplay(_EGL_PLATFORM_X11,
- native_display,
- attrib_list);
-
- if (!display) {
- _eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
- return NULL;
- }
-
- if (!_eglParseX11DisplayAttribList(display, attrib_list)) {
- return NULL;
+ /* EGL_EXT_platform_x11 recognizes exactly one attribute,
+ * EGL_PLATFORM_X11_SCREEN_EXT, which is optional.
+ */
+ if (attrib_list != NULL) {
+ for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+ if (attrib_list[i] != EGL_PLATFORM_X11_SCREEN_EXT) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+ return NULL;
+ }
+ }
}
-
- return display;
+ return _eglFindDisplay(_EGL_PLATFORM_X11, native_display, attrib_list);
}
#endif /* HAVE_X11_PLATFORM */
attrib_list);
}
#endif /* HAVE_SURFACELESS_PLATFORM */
+
+#ifdef HAVE_ANDROID_PLATFORM
+_EGLDisplay*
+_eglGetAndroidDisplay(void *native_display,
+ const EGLAttrib *attrib_list)
+{
+
+ /* This platform recognizes no display attributes. */
+ if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+ return NULL;
+ }
+
+ return _eglFindDisplay(_EGL_PLATFORM_ANDROID, native_display,
+ attrib_list);
+}
+#endif /* HAVE_ANDROID_PLATFORM */
+
+_EGLDisplay*
+_eglGetDeviceDisplay(void *native_display,
+ const EGLAttrib *attrib_list)
+{
+ _EGLDevice *dev;
+ _EGLDisplay *display;
+ int fd = -1;
+
+ dev = _eglLookupDevice(native_display);
+ if (!dev) {
+ _eglError(EGL_BAD_PARAMETER, "eglGetPlatformDisplay");
+ return NULL;
+ }
+
+ if (attrib_list) {
+ for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+ EGLAttrib attrib = attrib_list[i];
+ EGLAttrib value = attrib_list[i + 1];
+
+ /* EGL_EXT_platform_device does not recognize any attributes,
+ * EGL_EXT_device_drm adds the optional EGL_DRM_MASTER_FD_EXT.
+ */
+
+ if (!_eglDeviceSupports(dev, _EGL_DEVICE_DRM) ||
+ attrib != EGL_DRM_MASTER_FD_EXT) {
+ _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
+ return NULL;
+ }
+
+ fd = (int) value;
+ }
+ }
+
+ display = _eglFindDisplay(_EGL_PLATFORM_DEVICE, native_display, attrib_list);
+ if (!display) {
+ _eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
+ return NULL;
+ }
+
+ /* If the fd is explicitly provided and we did not dup() it yet, do so.
+ * The spec mandates that we do so, since we'll need it past the
+ * eglGetPlatformDispay call.
+ *
+ * The new fd is guaranteed to be 3 or greater.
+ */
+ if (fd != -1 && display->Options.fd == 0) {
+ display->Options.fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+ if (display->Options.fd == -1) {
+ /* Do not (really) need to teardown the display */
+ _eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
+ return NULL;
+ }
+ }
+
+ return display;
+}