summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/egl_helpers.c
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2021-07-23 20:08:05 -0500
committerDudemanguy <random342@airmail.cc>2021-07-25 15:32:53 +0000
commitf8e62d3d82dd0a3d06f9a557d756f0ad78118cc7 (patch)
treed4d75c6cee81456040450776b9f3ff20a486f978 /video/out/opengl/egl_helpers.c
parentbcf6077b28bdf0379a2671939ea5b79f2db31b51 (diff)
downloadmpv-f8e62d3d82dd0a3d06f9a557d756f0ad78118cc7.tar.bz2
mpv-f8e62d3d82dd0a3d06f9a557d756f0ad78118cc7.tar.xz
egl_helpers: fix create_context fallback behavior
The EGL stuff is really complicated because of historical reasons (tl;dr: blame EGL). There was one edge case with EGL context creation that lead to incorrect behavior. EGL_KHR_create_context was created with EGL 1.4 (which mpv does support) but it is still possible for an EGL 1.4 device to not implement this extension. That means that none of the EGL attrs that pass a specific opengl version work. So for this obscure case, there is a fallback context creation at the very end which simply creates an EGLContext without passing any special attrs. This has another problem however. mpv has a hard requirement on at least desktop opengl 2.1 or opengl ES 2.0 to function (we're not asking for much here). Since the fallback EGL context creation has no version checking, it is entirely possible to create an EGL context with a desktop opengl version under 2.1. As you get further along in the code, the user will encounter the hard opengl version check and then error out. However, we're supposed to also actually check if GLES works (that's what the opengl-es=auto option is for) so this is a bug. The fix is to do a bit of code duplication and make a mpgl_check_version specifically for if we hit the edge case of needing to create an EGL context without the EGL_KHR_create_context extension. Grab the version with the function pointer, check if it's under 210, if so destroy the EGL context and set it to NULL. After that, if the user has set opengl-es to auto, mpv will try GLES next. If it is set to no, then mpv will simply fail as desired. Fixes #5915. Sidenote: the ra_gl_ctx_test_version originally testing 140 doesn't make any sense. Passing the version number in that function only does something if the user has set opengl-restrict. What we need to do is to pass the version of the created context to that function. If the version is higher than the opengl-restrict option, then make this a failure.
Diffstat (limited to 'video/out/opengl/egl_helpers.c')
-rw-r--r--video/out/opengl/egl_helpers.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/video/out/opengl/egl_helpers.c b/video/out/opengl/egl_helpers.c
index ad026ba253..bcd85bfb73 100644
--- a/video/out/opengl/egl_helpers.c
+++ b/video/out/opengl/egl_helpers.c
@@ -78,6 +78,20 @@ static void dump_egl_config(struct mp_log *log, int msgl, EGLDisplay display,
}
}
+static void *mpegl_get_proc_address(void *ctx, const char *name)
+{
+ void *p = eglGetProcAddress(name);
+#if defined(__GLIBC__) && HAVE_LIBDL
+ // Some crappy ARM/Linux things do not provide EGL 1.5, so above call does
+ // not necessarily return function pointers for core functions. Try to get
+ // them from a loaded GLES lib. As POSIX leaves RTLD_DEFAULT "reserved",
+ // use it only with glibc.
+ if (!p)
+ p = dlsym(RTLD_DEFAULT, name);
+#endif
+ return p;
+}
+
// es_version: 0 (core), 2 or 3
static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
int es_version, struct mpegl_cb cb,
@@ -188,11 +202,20 @@ static bool create_context(struct ra_ctx *ctx, EGLDisplay display,
break;
}
- if (!egl_ctx && ra_gl_ctx_test_version(ctx, 140, false)) {
+ if (!egl_ctx) {
// Fallback for EGL 1.4 without EGL_KHR_create_context.
EGLint attrs[] = { EGL_NONE };
-
egl_ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, attrs);
+
+ GL *gl = talloc_zero(ctx, struct GL);
+ mpgl_check_version(gl, mpegl_get_proc_address, NULL);
+ if (gl->version < 210 ||
+ !ra_gl_ctx_test_version(ctx, gl->version, false))
+ {
+ eglDestroyContext(display, egl_ctx);
+ egl_ctx = NULL;
+ }
+ talloc_free(gl);
}
}
@@ -252,20 +275,6 @@ static int GLAPIENTRY swap_interval(int interval)
return !eglSwapInterval(display, interval);
}
-static void *mpegl_get_proc_address(void *ctx, const char *name)
-{
- void *p = eglGetProcAddress(name);
-#if defined(__GLIBC__) && HAVE_LIBDL
- // Some crappy ARM/Linux things do not provide EGL 1.5, so above call does
- // not necessarily return function pointers for core functions. Try to get
- // them from a loaded GLES lib. As POSIX leaves RTLD_DEFAULT "reserved",
- // use it only with glibc.
- if (!p)
- p = dlsym(RTLD_DEFAULT, name);
-#endif
- return p;
-}
-
// Load gl version and function pointers into *gl.
// Expects a current EGL context set.
void mpegl_load_functions(struct GL *gl, struct mp_log *log)