From c237539d62184ce3b78c502067da6b696b95538f Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 2 Aug 2017 15:55:08 -0400 Subject: [PATCH] egl: Implement EGL_EXT_explicit_device Implement support for EGL_EXT_explicit_device[1]. [1] https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_explicit_device.txt Signed-off-by: Adam Jackson Signed-off-by: Robert Foss Reviewed-by: Eric Engestrom Part-of: --- src/egl/drivers/dri2/platform_drm.c | 27 +++++- src/egl/main/egldisplay.c | 140 +++++++++++++++++++++++----- src/egl/main/eglglobals.c | 1 + 3 files changed, 141 insertions(+), 27 deletions(-) diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index 672ecdb1d77..94d3d52766c 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -39,6 +39,7 @@ #include "util/os_file.h" #include "egl_dri2.h" +#include "egldevice.h" #include "loader.h" static struct gbm_bo * @@ -579,10 +580,28 @@ dri2_initialize_drm(_EGLDisplay *disp) gbm = disp->PlatformDisplay; if (gbm == NULL) { - char buf[64]; - int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0); - if (n != -1 && n < sizeof(buf)) - dri2_dpy->fd_render_gpu = loader_open_device(buf); + if (disp->Device) { + drmDevicePtr drm = _eglDeviceDrm(disp->Device); + + if (!_eglDeviceSupports(disp->Device, _EGL_DEVICE_DRM)) { + err = "DRI2: Device isn't of _EGL_DEVICE_DRM type"; + goto cleanup; + } + + if (!(drm->available_nodes & (1 << DRM_NODE_PRIMARY))) { + err = "DRI2: Device does not have DRM_NODE_PRIMARY node"; + goto cleanup; + } + + dri2_dpy->fd_render_gpu = + loader_open_device(drm->nodes[DRM_NODE_PRIMARY]); + } else { + char buf[64]; + int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0); + if (n != -1 && n < sizeof(buf)) + dri2_dpy->fd_render_gpu = loader_open_device(buf); + } + gbm = gbm_create_device(dri2_dpy->fd_render_gpu); if (gbm == NULL) { err = "DRI2: failed to create gbm device"; diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index dd36a91e0d7..2bfe271f520 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -474,18 +474,45 @@ _eglUnlinkResource(_EGLResource *res, _EGLResourceType type) _EGLDisplay * _eglGetX11Display(Display *native_display, const EGLAttrib *attrib_list) { - /* EGL_EXT_platform_x11 recognizes exactly one attribute, - * EGL_PLATFORM_X11_SCREEN_EXT, which is optional. + _EGLDisplay *dpy; + _EGLDevice *dev = NULL; + + /* EGL_EXT_platform_x11 adds 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) { + EGLAttrib attrib = attrib_list[i]; + EGLAttrib value = attrib_list[i + 1]; + + switch (attrib) { + case EGL_DEVICE_EXT: + dev = _eglLookupDevice((void *)value); + if (!dev) { + _eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay"); + return NULL; + } + break; + + /* EGL_EXT_platform_x11 adds EGL_PLATFORM_X11_SCREEN_EXT, + * which is optional. + */ + case EGL_PLATFORM_X11_SCREEN_EXT: + break; + + default: _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); return NULL; } } } - return _eglFindDisplay(_EGL_PLATFORM_X11, native_display, attrib_list); + + dpy = _eglFindDisplay(_EGL_PLATFORM_X11, native_display, attrib_list); + if (dpy && dev) { + dpy->Device = dev; + } + + return dpy; } #endif /* HAVE_X11_PLATFORM */ @@ -494,19 +521,42 @@ _EGLDisplay * _eglGetXcbDisplay(xcb_connection_t *native_display, const EGLAttrib *attrib_list) { + _EGLDisplay *dpy; + _EGLDevice *dev = NULL; + /* EGL_EXT_platform_xcb recognizes exactly one attribute, * EGL_PLATFORM_XCB_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_XCB_SCREEN_EXT) { + EGLAttrib attrib = attrib_list[i]; + EGLAttrib value = attrib_list[i + 1]; + + switch (attrib) { + case EGL_DEVICE_EXT: + dev = _eglLookupDevice((void *)value); + if (!dev) { + _eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay"); + return NULL; + } + break; + + case EGL_PLATFORM_XCB_SCREEN_EXT: + break; + + default: _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); return NULL; } } } - return _eglFindDisplay(_EGL_PLATFORM_XCB, native_display, attrib_list); + dpy = _eglFindDisplay(_EGL_PLATFORM_XCB, native_display, attrib_list); + if (dpy && dev) { + dpy->Device = dev; + } + + return dpy; } #endif /* HAVE_XCB_PLATFORM */ @@ -515,13 +565,28 @@ _EGLDisplay * _eglGetGbmDisplay(struct gbm_device *native_display, const EGLAttrib *attrib_list) { - /* EGL_MESA_platform_gbm recognizes no attributes. */ - if (attrib_list != NULL && attrib_list[0] != EGL_NONE) { - _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); - return NULL; + _EGLDisplay *dpy; + _EGLDevice *dev = NULL; + + /* This platform recognizes only EXT_explicit_device */ + if (attrib_list) { + if (attrib_list[0] != EGL_DEVICE_EXT) { + _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); + return NULL; + } + dev = _eglLookupDevice((void *)attrib_list[1]); + if (!dev) { + _eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay"); + return NULL; + } } - return _eglFindDisplay(_EGL_PLATFORM_DRM, native_display, attrib_list); + dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, native_display, attrib_list); + if (dpy) { + dpy->Device = dev; + } + + return dpy; } #endif /* HAVE_DRM_PLATFORM */ @@ -530,33 +595,62 @@ _EGLDisplay * _eglGetWaylandDisplay(struct wl_display *native_display, const EGLAttrib *attrib_list) { - /* EGL_EXT_platform_wayland recognizes no attributes. */ - if (attrib_list != NULL && attrib_list[0] != EGL_NONE) { - _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); - return NULL; + _EGLDisplay *dpy; + _EGLDevice *dev = NULL; + + /* This platform recognizes only EXT_explicit_device */ + if (attrib_list) { + if (attrib_list[0] != EGL_DEVICE_EXT) { + _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); + return NULL; + } + dev = _eglLookupDevice((void *)attrib_list[1]); + if (!dev) { + _eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay"); + return NULL; + } } - return _eglFindDisplay(_EGL_PLATFORM_WAYLAND, native_display, attrib_list); + dpy = _eglFindDisplay(_EGL_PLATFORM_WAYLAND, native_display, attrib_list); + if (dpy) { + dpy->Device = dev; + } + + return dpy; } #endif /* HAVE_WAYLAND_PLATFORM */ _EGLDisplay * _eglGetSurfacelessDisplay(void *native_display, const EGLAttrib *attrib_list) { - /* This platform has no native display. */ + _EGLDisplay *dpy; + + /* Any native display must be an EGLDeviceEXT we know about */ if (native_display != NULL) { _eglError(EGL_BAD_PARAMETER, "eglGetPlatformDisplay"); return NULL; } - /* This platform recognizes no display attributes. */ - if (attrib_list != NULL && attrib_list[0] != EGL_NONE) { - _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); - return NULL; + /* This platform recognizes only EXT_explicit_device */ + if (attrib_list) { + if (attrib_list[0] != EGL_DEVICE_EXT) { + _eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay"); + return NULL; + } + if ((native_display && native_display != (void *)attrib_list[1]) || + (native_display != _eglLookupDevice(native_display))) { + _eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay"); + return NULL; + } } - return _eglFindDisplay(_EGL_PLATFORM_SURFACELESS, native_display, - attrib_list); + dpy = + _eglFindDisplay(_EGL_PLATFORM_SURFACELESS, native_display, attrib_list); + if (dpy) { + dpy->Device = native_display; + } + + return dpy; } #ifdef HAVE_ANDROID_PLATFORM diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index 3d12e6d5eae..926332a7b66 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -83,6 +83,7 @@ struct _egl_global _eglGlobal = { #if !DETECT_OS_WINDOWS "EGL_EXT_platform_device" + " EGL_EXT_explicit_device" #endif #ifdef HAVE_WAYLAND_PLATFORM " EGL_EXT_platform_wayland"