From b69af0abefd7fa78fbc5c233e264c9155b091ad9 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 15 Nov 2021 22:51:33 +0100 Subject: [PATCH] egl_helpers: introduce wrapper around eglCreatePlatformWindowSurface It abstracts EGL 1.5, extension checks and other inconsistencies away. This can be used in context code as the (preferred) alternative to eglCreateWindowSurface(). --- video/out/opengl/egl_helpers.c | 59 +++++++++++++++++++++++++++------- video/out/opengl/egl_helpers.h | 3 ++ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/video/out/opengl/egl_helpers.c b/video/out/opengl/egl_helpers.c index 6c3604daa5..b3e11c6f43 100644 --- a/video/out/opengl/egl_helpers.c +++ b/video/out/opengl/egl_helpers.c @@ -276,6 +276,20 @@ void mpegl_load_functions(struct GL *gl, struct mp_log *log) gl->SwapInterval = swap_interval; } +static bool is_egl15(void) +{ + // It appears that EGL 1.4 is specified to _require_ an initialized display + // for EGL_VERSION, while EGL 1.5 is _required_ to return the EGL version. + const char *ver = eglQueryString(EGL_NO_DISPLAY, EGL_VERSION); + // Of course we have to go through the excruciating pain of parsing a + // version string, since EGL provides no other way without a display. In + // theory version!=NULL is already proof enough that it's 1.5, but be + // extra defensive, since this should have been true for EGL_EXTENSIONS as + // well, but then they added an extension that modified standard behavior. + int ma = 0, mi = 0; + return ver && sscanf(ver, "%d.%d", &ma, &mi) == 2 && (ma > 1 || mi >= 5); +} + // This is similar to eglGetPlatformDisplay(platform, native_display, NULL), // except that it 1. may use eglGetPlatformDisplayEXT, 2. checks for the // platform client extension platform_ext_name, and 3. does not support passing @@ -310,16 +324,7 @@ EGLDisplay mpegl_get_display(EGLenum platform, const char *platform_ext_name, return EGL_NO_DISPLAY; // Before we go through the EGL 1.4 BS, try if we can use native EGL 1.5 - // It appears that EGL 1.4 is specified to _require_ an initialized display - // for EGL_VERSION, while EGL 1.5 is _required_ to return the EGL version. - const char *ver = eglQueryString(EGL_NO_DISPLAY, EGL_VERSION); - // Of course we have to go through the excruciating pain of parsing a - // version string, since EGL provides no other way without a display. In - // theory version!=NULL is already proof enough that it's 1.5, but be - // extra defensive, since this should have been true for EGL_EXTENSIONS as - // well, but then they added an extension that modified standard behavior. - int ma = 0, mi = 0; - if (ver && sscanf(ver, "%d.%d", &ma, &mi) == 2 && (ma > 1 || mi >= 5)) { + if (is_egl15()) { // This is EGL 1.5. It must support querying standard functions through // eglGetProcAddress(). Note that on EGL 1.4, even if the function is // unknown, it could return non-NULL anyway (because EGL is crazy). @@ -331,8 +336,7 @@ EGLDisplay mpegl_get_display(EGLenum platform, const char *platform_ext_name, return GetPlatformDisplay(platform, native_display, NULL); } - // (It should be impossible to be missing, but uh.) - if (!gl_check_extension(exts, "EGL_EXT_client_extensions")) + if (!gl_check_extension(exts, "EGL_EXT_platform_base")) return EGL_NO_DISPLAY; EGLDisplay (EGLAPIENTRYP GetPlatformDisplayEXT)(EGLenum, void*, const EGLint*) @@ -344,3 +348,34 @@ EGLDisplay mpegl_get_display(EGLenum platform, const char *platform_ext_name, return EGL_NO_DISPLAY; } + +// The same mess but with eglCreatePlatformWindowSurface(EXT) +// again no support for an attribute list because the type differs +// Returns EGL_NO_SURFACE on failure. +EGLSurface mpegl_create_window_surface(EGLDisplay dpy, EGLConfig config, + void *native_window) +{ + // Use the EGL 1.5 function if possible + if (is_egl15()) { + EGLSurface (EGLAPIENTRYP CreatePlatformWindowSurface) + (EGLDisplay, EGLConfig, void *, const EGLAttrib *) = + (void *)eglGetProcAddress("eglCreatePlatformWindowSurface"); + // (It should be impossible to be NULL, but uh.) + if (CreatePlatformWindowSurface) + return CreatePlatformWindowSurface(dpy, config, native_window, NULL); + } + + // Check the extension that provides the *EXT function + const char *exts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (!gl_check_extension(exts, "EGL_EXT_platform_base")) + return EGL_NO_SURFACE; + + EGLSurface (EGLAPIENTRYP CreatePlatformWindowSurfaceEXT) + (EGLDisplay, EGLConfig, void *, const EGLint *) = + (void *)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); + // (It should be impossible to be NULL, but uh.) + if (CreatePlatformWindowSurfaceEXT) + return CreatePlatformWindowSurfaceEXT(dpy, config, native_window, NULL); + + return EGL_NO_SURFACE; +} diff --git a/video/out/opengl/egl_helpers.h b/video/out/opengl/egl_helpers.h index bbd274e613..32ec5d12e4 100644 --- a/video/out/opengl/egl_helpers.h +++ b/video/out/opengl/egl_helpers.h @@ -32,4 +32,7 @@ void mpegl_load_functions(struct GL *gl, struct mp_log *log); EGLDisplay mpegl_get_display(EGLenum platform, const char *platform_ext_name, void *native_display); +EGLSurface mpegl_create_window_surface(EGLDisplay dpy, EGLConfig config, + void *native_window); + #endif