From b5a4b16799a30cb74db1916d52f2756a7a5345ed Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 30 Apr 2018 15:26:17 -0400 Subject: [PATCH 1/2] dispatch: Query the EGL context version when bootstrapping on GLES We're about to change our dlopen paths to do RTLD_NOLOAD more aggressively. The issue then is we can create an EGL GLES context without libGLES* ever being loaded. test/egl_gles2_without_glx will fail in such a world: the first gentle probe for libGLESv2 will fail, then the less-gentle probe for libGLESv1_CM will be shot down by the test, and we exit. Fortunately by the time we've gotten to this point the context exists, so we can query its version via EGL instead. Signed-off-by: Adam Jackson --- src/dispatch_common.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/dispatch_common.c b/src/dispatch_common.c index 1eccb3b..bf10d52 100644 --- a/src/dispatch_common.c +++ b/src/dispatch_common.c @@ -812,20 +812,20 @@ epoxy_get_bootstrap_proc_address(const char *name) #if PLATFORM_HAS_EGL get_dlopen_handle(&api.egl_handle, EGL_LIB, false); if (api.egl_handle) { + int version = 0; switch (epoxy_egl_get_current_gl_context_api()) { case EGL_OPENGL_API: return epoxy_gl_dlsym(name); case EGL_OPENGL_ES_API: - /* We can't resolve the GL version, because - * epoxy_glGetString() is one of the two things calling - * us. Try the GLES2 implementation first, and fall back - * to GLES1 otherwise. - */ - get_dlopen_handle(&api.gles2_handle, GLES2_LIB, false); - if (api.gles2_handle) - return epoxy_gles2_dlsym(name); - else - return epoxy_gles1_dlsym(name); + if (eglQueryContext(eglGetCurrentDisplay(), + eglGetCurrentContext(), + EGL_CONTEXT_CLIENT_VERSION, + &version)) { + if (version >= 2) + return epoxy_gles2_dlsym(name); + else + return epoxy_gles1_dlsym(name); + } } } #endif /* PLATFORM_HAS_EGL */ From a33623dca7cc430a9edecdc44f1c76bfb251d576 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 9 Apr 2018 16:10:52 -0400 Subject: [PATCH 2/2] dispatch: Be even gentler about probing for GLX dlsym(NULL) can only see (symbols in) libraries that are loaded RTLD_GLOBAL, but our dlopen()s are RTLD_LOCAL and probably so was the one the app did if it did one. So use RTLD_NOLOAD to probe for the library even if it's LOCAL, iff the lookup is non-fatal. Having done that, don't ever load any libraries on this path. We only perform this check while resolving rendering API functions, and the window system resolution paths already load the appropriate library if they need to. Since you have to have gone through a winsys to get a context, and our resolvers only run when a function is _called_, this would only introduce a failure mode if you tried to call a function without a context bound. Signed-off-by: Adam Jackson --- src/dispatch_common.c | 41 +++++++---------------------------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/dispatch_common.c b/src/dispatch_common.c index bf10d52..244938b 100644 --- a/src/dispatch_common.c +++ b/src/dispatch_common.c @@ -305,7 +305,11 @@ get_dlopen_handle(void **handle, const char *lib_name, bool exit_on_fail) #else pthread_mutex_lock(&api.mutex); if (!*handle) { - *handle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); + int flags = RTLD_LAZY | RTLD_LOCAL; + if (!exit_on_fail) + flags |= RTLD_NOLOAD; + + *handle = dlopen(lib_name, flags); if (!*handle) { if (exit_on_fail) { fprintf(stderr, "Couldn't open %s: %s\n", lib_name, dlerror()); @@ -572,23 +576,7 @@ epoxy_current_context_is_glx(void) #else void *sym; - /* If we've been called already, don't load more */ - if (!api.egl_handle != !api.glx_handle) { - if (api.glx_handle) - return true; - else if (api.egl_handle) - return false; - } - - /* If the application hasn't explicitly called some of our GLX - * or EGL code but has presumably set up a context on its own, - * then we need to figure out how to getprocaddress anyway. - * - * If there's a public GetProcAddress loaded in the - * application's namespace, then use that. - */ - - sym = dlsym(NULL, "glXGetCurrentContext"); + sym = epoxy_conservative_glx_dlsym("glXGetCurrentContext", false); if (sym) { if (glXGetCurrentContext()) return true; @@ -597,7 +585,7 @@ epoxy_current_context_is_glx(void) } #if PLATFORM_HAS_EGL - sym = dlsym(NULL, "eglGetCurrentContext"); + sym = epoxy_conservative_egl_dlsym("eglGetCurrentContext", false); if (sym) { if (epoxy_egl_get_current_gl_context_api() != EGL_NONE) return false; @@ -606,21 +594,6 @@ epoxy_current_context_is_glx(void) } #endif /* PLATFORM_HAS_EGL */ - /* OK, couldn't find anything in the app's address space. - * Presumably they dlopened with RTLD_LOCAL, which hides it - * from us. Just go dlopen()ing likely libraries and try them. - */ - sym = epoxy_conservative_glx_dlsym("glXGetCurrentContext", false); - if (sym && glXGetCurrentContext()) - return true; - -#if PLATFORM_HAS_EGL - sym = do_dlsym(&api.egl_handle, EGL_LIB, "eglGetCurrentContext", - false); - if (sym && epoxy_egl_get_current_gl_context_api() != EGL_NONE) - return false; -#endif /* PLATFORM_HAS_EGL */ - return false; #endif /* PLATFORM_HAS_GLX */ }