summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-12-12 01:50:05 +0100
committerwm4 <wm4@nowhere>2019-12-12 01:50:05 +0100
commitcc746c9508a2e64a69cb75ea7b9ec8ac437934ff (patch)
treee38aa9ed6df16fcbef8d7d33f16288aac708b767
parentdb3754d8d6f93e37edf4238dc1b9b0de62963b47 (diff)
downloadmpv-cc746c9508a2e64a69cb75ea7b9ec8ac437934ff.tar.bz2
mpv-cc746c9508a2e64a69cb75ea7b9ec8ac437934ff.tar.xz
vo_gpu: x11egl: cleanup EGL correctly
...probably. The EGL backend had a strange problem: when recreating the window, EGL surface creation sometimes mysteriously failed. For example, keeping the "_" key down (cycles video by default) destroys and recreates the window in rapid succession, which will often enough show the "Could not create EGL surface!" message. This was puzzling because due to mpv's architecture, the X11 Window and even the X11 Display were fully destroyed, the thread on which they ran was destroyed, and then everything was recreated. There shouldn't have been any state that could make subsequent EGL initialization fail. It turns out mpv forgot to free EGLSurfaces in the x11 code. EGL is a pretty crazy API (full of thread local and global state with weird lifetime requirements), and for example it seems EGLDisplay cannot be explicitly released, but apparently implicitly dies when the native display is closed (at least EGL 1.5 claims eglTerminate() does _not_ invalidate the display, only certain objects linked to it). It appears that Mesa still referenced at least EGLSurface in some form, and either some pointer or some X11 ID was dangling, and when it randomly matched when eglCreateWindowSurface() was called, it failed. Fix this by calling eglTerminate(), which supposedly destroys (or rather unreferences) contexts and surfaces created from the display (but absurdly not the display itself). Now why can't you just destroy the display? If it's implicitly invalidated, why can't it just call eglTerminate() implicitly when this happens? Did Mesa do something wrong when they somehow didn't automatically remove the dangling object (so I could claim not to be responsible for the bug)? Who the fuck knows, and I'm too tired to figure this out (both because it's late, and because I'm tired of this EGL crap API). Still not sure if the code is correct now. I think EGL was designed to maximize implementation and API-use complications. How else could you possibly come up with something like the EGLDisplay life cycle? Or am I just making a fuss? Anyway, fuck EGL, fuck computers, fuck technology. Fixes: #7129
-rw-r--r--video/out/opengl/context_x11egl.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/video/out/opengl/context_x11egl.c b/video/out/opengl/context_x11egl.c
index e86b99bb36..15a9600de7 100644
--- a/video/out/opengl/context_x11egl.c
+++ b/video/out/opengl/context_x11egl.c
@@ -44,12 +44,9 @@ static void mpegl_uninit(struct ra_ctx *ctx)
struct priv *p = ctx->priv;
ra_gl_ctx_uninit(ctx);
- if (p->egl_context) {
- eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglDestroyContext(p->egl_display, p->egl_context);
- }
- p->egl_context = EGL_NO_CONTEXT;
+ eglMakeCurrent(p->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglTerminate(p->egl_display);
vo_x11_uninit(ctx->vo);
}