diff --git a/gfx/common/egl_common.c b/gfx/common/egl_common.c index db76d0c9f1..bdcddf8bad 100644 --- a/gfx/common/egl_common.c +++ b/gfx/common/egl_common.c @@ -208,12 +208,129 @@ void egl_get_video_size(egl_ctx_data_t *egl, unsigned *width, unsigned *height) } } +static bool check_egl_version(int minMajorVersion, int minMinorVersion) +{ + const char *str = eglQueryString(EGL_NO_DISPLAY, EGL_VERSION); + int major, minor; + int count; + + if (str == NULL) + { + return false; + } + + count = sscanf(str, "%d.%d", &major, &minor); + if (count != 2) + { + return false; + } + + if (major < minMajorVersion) + { + return false; + } + else if (major > minMajorVersion) + { + return true; + } + else if (minor >= minMinorVersion) + { + return true; + } + else + { + return false; + } +} + +static bool check_egl_client_extension(const char *name) +{ + const char *str; + size_t nameLen; + + str = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (str == NULL) + { + // The EGL implementation doesn't support client extensions at all. + return false; + } + + nameLen = strlen(name); + while (*str != '\0') + { + // Use strspn and strcspn to find the start position and length of each + // token in the extension string. Using strtok could also work, but + // that would require allocating a copy of the string. + size_t len = strcspn(str, " "); + if (len == nameLen && strncmp(str, name, nameLen) == 0) + { + return true; + } + str += len; + str += strspn(str, " "); + } + + return false; +} + +static EGLDisplay get_egl_display(EGLenum platform, void *native) +{ + if (platform != EGL_NONE) + { + // If the client library supports at least EGL 1.5, then we can call + // eglGetPlatformDisplay. Otherwise, see if eglGetPlatformDisplayEXT + // is available. + if (check_egl_version(1, 5)) + { + typedef EGLDisplay (EGLAPIENTRY * pfn_eglGetPlatformDisplay) + (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); + pfn_eglGetPlatformDisplay ptr_eglGetPlatformDisplay; + + RARCH_LOG("[EGL] Found EGL client version >= 1.5, trying eglGetPlatformDisplay\n"); + ptr_eglGetPlatformDisplay = (pfn_eglGetPlatformDisplay) + eglGetProcAddress("eglGetPlatformDisplay"); + if (ptr_eglGetPlatformDisplay != NULL) + { + EGLDisplay dpy = ptr_eglGetPlatformDisplay(platform, native, NULL); + if (dpy != EGL_NO_DISPLAY) + { + return dpy; + } + } + } + + if (check_egl_client_extension("EGL_EXT_platform_base")) + { + PFNEGLGETPLATFORMDISPLAYEXTPROC ptr_eglGetPlatformDisplayEXT; + + RARCH_LOG("[EGL] Found EGL_EXT_platform_base, trying eglGetPlatformDisplayEXT\n"); + ptr_eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC) + eglGetProcAddress("eglGetPlatformDisplayEXT"); + if (ptr_eglGetPlatformDisplayEXT != NULL) + { + EGLDisplay dpy = ptr_eglGetPlatformDisplayEXT(platform, native, NULL); + if (dpy != EGL_NO_DISPLAY) + { + return dpy; + } + } + } + } + + // Either the caller didn't provide a platform type, or the EGL + // implementation doesn't support eglGetPlatformDisplay. In this case, try + // eglGetDisplay and hope for the best. + RARCH_LOG("[EGL] Falling back to eglGetDisplay\n"); + return eglGetDisplay((EGLNativeDisplayType) native); +} + bool egl_init_context(egl_ctx_data_t *egl, + EGLenum platform, void *display_data, EGLint *major, EGLint *minor, EGLint *n, const EGLint *attrib_ptr) { - EGLDisplay dpy = (NativeDisplayType)eglGetDisplay((EGLNativeDisplayType)display_data); + EGLDisplay dpy = get_egl_display(platform, display_data); if (dpy == EGL_NO_DISPLAY) { RARCH_ERR("[EGL]: Couldn't get EGL display.\n"); diff --git a/gfx/common/egl_common.h b/gfx/common/egl_common.h index 6df02a5f39..5e1dbc8ad1 100644 --- a/gfx/common/egl_common.h +++ b/gfx/common/egl_common.h @@ -89,6 +89,7 @@ void egl_set_swap_interval(egl_ctx_data_t *egl, unsigned interval); void egl_get_video_size(egl_ctx_data_t *egl, unsigned *width, unsigned *height); bool egl_init_context(egl_ctx_data_t *egl, + EGLenum platform, void *display_data, EGLint *major, EGLint *minor, diff --git a/gfx/drivers_context/android_ctx.c b/gfx/drivers_context/android_ctx.c index 13e6e66ca7..b721c8467b 100644 --- a/gfx/drivers_context/android_ctx.c +++ b/gfx/drivers_context/android_ctx.c @@ -143,7 +143,7 @@ static void *android_gfx_ctx_init(video_frame_info_t *video_info, void *video_dr #ifdef HAVE_EGL RARCH_LOG("Android EGL: GLES version = %d.\n", g_es3 ? 3 : 2); - if (!egl_init_context(&and->egl, EGL_DEFAULT_DISPLAY, + if (!egl_init_context(&and->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); diff --git a/gfx/drivers_context/drm_ctx.c b/gfx/drivers_context/drm_ctx.c index ae61ccb819..4f9391e211 100644 --- a/gfx/drivers_context/drm_ctx.c +++ b/gfx/drivers_context/drm_ctx.c @@ -563,7 +563,8 @@ static bool gfx_ctx_drm_egl_set_video_mode(gfx_ctx_drm_data_t *drm) case GFX_CTX_OPENGL_ES_API: case GFX_CTX_OPENVG_API: #ifdef HAVE_EGL - if (!egl_init_context(&drm->egl, (EGLNativeDisplayType)g_gbm_dev, &major, + if (!egl_init_context(&drm->egl, EGL_PLATFORM_GBM_KHR, + (EGLNativeDisplayType)g_gbm_dev, &major, &minor, &n, attrib_ptr)) goto error; diff --git a/gfx/drivers_context/emscriptenegl_ctx.c b/gfx/drivers_context/emscriptenegl_ctx.c index 6d6c50cf86..8212507112 100644 --- a/gfx/drivers_context/emscriptenegl_ctx.c +++ b/gfx/drivers_context/emscriptenegl_ctx.c @@ -135,7 +135,7 @@ static void *gfx_ctx_emscripten_init(video_frame_info_t *video_info, void *video return (void*)"emscripten"; } - if (!egl_init_context(&emscripten->egl, EGL_DEFAULT_DISPLAY, + if (!egl_init_context(&emscripten->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribute_list)) { egl_report_error(); diff --git a/gfx/drivers_context/mali_fbdev_ctx.c b/gfx/drivers_context/mali_fbdev_ctx.c index 5d8b9d3d6c..12b8ce430f 100644 --- a/gfx/drivers_context/mali_fbdev_ctx.c +++ b/gfx/drivers_context/mali_fbdev_ctx.c @@ -116,7 +116,7 @@ static void *gfx_ctx_mali_fbdev_init(video_frame_info_t *video_info, void *video #endif #ifdef HAVE_EGL - if (!egl_init_context(&mali->egl, EGL_DEFAULT_DISPLAY, + if (!egl_init_context(&mali->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); diff --git a/gfx/drivers_context/opendingux_fbdev_ctx.c b/gfx/drivers_context/opendingux_fbdev_ctx.c index 3af8154f97..9cccc1ac51 100644 --- a/gfx/drivers_context/opendingux_fbdev_ctx.c +++ b/gfx/drivers_context/opendingux_fbdev_ctx.c @@ -83,7 +83,7 @@ static void *gfx_ctx_opendingux_init(video_frame_info_t *video_info, void *video #ifdef HAVE_EGL frontend_driver_install_signal_handler(); - if (!egl_init_context(&viv->egl, EGL_DEFAULT_DISPLAY, + if (!egl_init_context(&viv->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { diff --git a/gfx/drivers_context/qnx_ctx.c b/gfx/drivers_context/qnx_ctx.c index 3ac5c734fb..37c9b654fb 100644 --- a/gfx/drivers_context/qnx_ctx.c +++ b/gfx/drivers_context/qnx_ctx.c @@ -131,7 +131,7 @@ static void *gfx_ctx_qnx_init(video_frame_info_t *video_info, void *video_driver #ifdef HAVE_EGL - if (!egl_init_context(&qnx->egl, EGL_DEFAULT_DISPLAY, &major, &minor, + if (!egl_init_context(&qnx->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); diff --git a/gfx/drivers_context/vc_egl_ctx.c b/gfx/drivers_context/vc_egl_ctx.c index a9fa66f247..26e5eea378 100644 --- a/gfx/drivers_context/vc_egl_ctx.c +++ b/gfx/drivers_context/vc_egl_ctx.c @@ -183,7 +183,7 @@ static void *gfx_ctx_vc_init(video_frame_info_t *video_info, void *video_driver) bcm_host_init(); #ifdef HAVE_EGL - if (!egl_init_context(&vc->egl, EGL_DEFAULT_DISPLAY, + if (!egl_init_context(&vc->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribute_list)) { egl_report_error(); diff --git a/gfx/drivers_context/vivante_fbdev_ctx.c b/gfx/drivers_context/vivante_fbdev_ctx.c index 88a9edb0e7..6d8e0728f5 100644 --- a/gfx/drivers_context/vivante_fbdev_ctx.c +++ b/gfx/drivers_context/vivante_fbdev_ctx.c @@ -90,7 +90,7 @@ static void *gfx_ctx_vivante_init(video_frame_info_t *video_info, void *video_dr system("setterm -cursor off"); #ifdef HAVE_EGL - if (!egl_init_context(&viv->egl, EGL_DEFAULT_DISPLAY, &major, &minor, + if (!egl_init_context(&viv->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 138d2b5537..6b1ac60e5e 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -900,6 +900,7 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) case GFX_CTX_OPENVG_API: #ifdef HAVE_EGL if (!egl_init_context(&wl->egl, + EGL_PLATFORM_WAYLAND_KHR, (EGLNativeDisplayType)wl->dpy, &major, &minor, &n, attrib_ptr)) { diff --git a/gfx/drivers_context/xegl_ctx.c b/gfx/drivers_context/xegl_ctx.c index 07977f5f25..08b57c9c70 100644 --- a/gfx/drivers_context/xegl_ctx.c +++ b/gfx/drivers_context/xegl_ctx.c @@ -163,8 +163,8 @@ static void *gfx_ctx_xegl_init(video_frame_info_t *video_info, void *video_drive goto error; #ifdef HAVE_EGL - if (!egl_init_context(&xegl->egl, (EGLNativeDisplayType)g_x11_dpy, - &major, &minor, &n, attrib_ptr)) + if (!egl_init_context(&xegl->egl, EGL_PLATFORM_X11_KHR, + (EGLNativeDisplayType)g_x11_dpy, &major, &minor, &n, attrib_ptr)) { egl_report_error(); goto error;