diff --git a/libmpv/opengl_cb.h b/libmpv/opengl_cb.h index bd694b61d4..112f254a59 100644 --- a/libmpv/opengl_cb.h +++ b/libmpv/opengl_cb.h @@ -126,6 +126,16 @@ extern "C" { * up until mpv_opengl_cb_uninit_gl() is called. If the name is not anything * you know/expected, return NULL from the function. * + * Windowing system interop on Linux + * --------------------------------- + * + * The new VAAPI OpenGL interop requires an EGL context. EGL provides no way + * to query the X11 Display associated to a specific EGL context, so this API + * is used to pass it through. + * + * glMPGetNativeDisplay("x11") should return a X11 "Display*", which then will + * be used to create the hardware decoder state. (On GLX, this is not needed.) + * * Windowing system interop on MS win32 * ------------------------------------ * diff --git a/video/out/opengl/x11egl.c b/video/out/opengl/x11egl.c index 53cd5ae677..87e0e89fff 100644 --- a/video/out/opengl/x11egl.c +++ b/video/out/opengl/x11egl.c @@ -20,6 +20,8 @@ * version 2.1 of the License, or (at your option) any later version. */ +#include + #include #include #include @@ -29,11 +31,21 @@ #include "common.h" struct priv { + Display *x_display; EGLDisplay egl_display; EGLContext egl_context; EGLSurface egl_surface; }; +static _Thread_local struct priv *current_context; + +static void * GLAPIENTRY get_native_display(const char *name) +{ + if (current_context && strcmp(name, "x11") == 0) + return current_context->x_display; + return NULL; +} + static EGLConfig select_fb_config_egl(struct MPGLContext *ctx, bool es) { struct priv *p = ctx->priv; @@ -99,6 +111,8 @@ static bool config_window_x11_egl(struct MPGLContext *ctx, int flags) struct vo *vo = ctx->vo; bool es = flags & VOFLAG_GLES; + p->x_display = vo->x11->display; + if (!eglBindAPI(es ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) { MP_FATAL(vo, "Could not bind API (%s).\n", es ? "GLES" : "GL"); return false; @@ -138,7 +152,10 @@ static bool config_window_x11_egl(struct MPGLContext *ctx, int flags) void *(*gpa)(const GLubyte*) = (void *(*)(const GLubyte*))eglGetProcAddress; mpgl_load_functions(ctx->gl, gpa, egl_exts, vo->log); + ctx->gl->MPGetNativeDisplay = get_native_display; + assert(!current_context); + current_context = p; return true; } @@ -171,6 +188,7 @@ static void mpegl_uninit(MPGLContext *ctx) eglDestroyContext(p->egl_display, p->egl_context); } p->egl_context = EGL_NO_CONTEXT; + current_context = NULL; vo_x11_uninit(ctx->vo); } diff --git a/wscript b/wscript index f23cf43500..22cc4693d1 100644 --- a/wscript +++ b/wscript @@ -172,6 +172,10 @@ main_dependencies = [ 'desc': 'compiler support for usable thread synchronization built-ins', 'func': check_true, 'deps_any': ['stdatomic', 'atomic-builtins', 'sync-builtins'], + }, { + 'name': 'c11-tls', + 'desc': 'C11 TLS support', + 'func': check_statement('stddef.h', 'static _Thread_local int x = 0'), }, { 'name': 'librt', 'desc': 'linking with -lrt', @@ -605,7 +609,7 @@ video_output_features = [ } , { 'name': '--egl-x11', 'desc': 'OpenGL X11 EGL Backend', - 'deps': [ 'x11' ], + 'deps': [ 'x11', 'c11-tls' ], 'groups': [ 'gl' ], 'func': check_pkg_config('egl', 'gl'), } , {