summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/opengl/context_wayland.c7
-rw-r--r--video/out/opengl/context_x11egl.c7
-rw-r--r--video/out/opengl/egl_helpers.c69
-rw-r--r--video/out/opengl/egl_helpers.h3
4 files changed, 82 insertions, 4 deletions
diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c
index 2dd8cdec29..8af5c7b9a6 100644
--- a/video/out/opengl/context_wayland.c
+++ b/video/out/opengl/context_wayland.c
@@ -28,6 +28,8 @@
// Generated from presentation-time.xml
#include "video/out/wayland/presentation-time.h"
+#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
+
struct priv {
GL gl;
EGLDisplay egl_display;
@@ -163,8 +165,9 @@ static bool egl_create_context(struct ra_ctx *ctx)
struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
struct vo_wayland_state *wl = ctx->vo->wl;
- if (!(p->egl_display = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR,
- wl->display, NULL)))
+ if (!(p->egl_display = mpegl_get_display(EGL_PLATFORM_WAYLAND_EXT,
+ "EGL_EXT_platform_wayland",
+ wl->display)))
return false;
if (eglInitialize(p->egl_display, NULL, NULL) != EGL_TRUE)
diff --git a/video/out/opengl/context_x11egl.c b/video/out/opengl/context_x11egl.c
index a829aad85e..812718a647 100644
--- a/video/out/opengl/context_x11egl.c
+++ b/video/out/opengl/context_x11egl.c
@@ -28,6 +28,8 @@
#include "oml_sync.h"
#include "utils.h"
+#define EGL_PLATFORM_X11_EXT 0x31D5
+
struct priv {
GL gl;
EGLDisplay egl_display;
@@ -101,8 +103,9 @@ static bool mpegl_init(struct ra_ctx *ctx)
if (!vo_x11_init(vo))
goto uninit;
- p->egl_display = eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR,
- vo->x11->display, NULL);
+ p->egl_display = mpegl_get_display(EGL_PLATFORM_X11_EXT,
+ "EGL_EXT_platform_x11",
+ vo->x11->display);
if (!eglInitialize(p->egl_display, NULL, NULL)) {
MP_MSG(ctx, msgl, "Could not initialize EGL.\n");
goto uninit;
diff --git a/video/out/opengl/egl_helpers.c b/video/out/opengl/egl_helpers.c
index 29057614b2..94a0e66eca 100644
--- a/video/out/opengl/egl_helpers.c
+++ b/video/out/opengl/egl_helpers.c
@@ -277,3 +277,72 @@ void mpegl_load_functions(struct GL *gl, struct mp_log *log)
if (!gl->SwapInterval)
gl->SwapInterval = swap_interval;
}
+
+// 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
+// an attrib list, because the type for that parameter is different in the EXT
+// and standard functions (EGL can't not fuck up, no matter what).
+// platform: e.g. EGL_PLATFORM_X11_KHR
+// platform_ext_name: e.g. "EGL_KHR_platform_x11"
+// native_display: e.g. X11 Display*
+// Returns EGL_NO_DISPLAY on failure.
+// Warning: the EGL version can be different at runtime depending on the chosen
+// platform, so this might return a display corresponding to some older EGL
+// version (often 1.4).
+// Often, there are two extension variants of a platform (KHR and EXT). If you
+// need to check both, call this function twice. (Why do they define them twice?
+// They're crazy.)
+EGLDisplay mpegl_get_display(EGLenum platform, const char *platform_ext_name,
+ void *native_display)
+{
+ // EGL is awful. Designed as ultra-portable library, it fails at dealing
+ // with slightly more complex environment than its short-sighted design
+ // could deal with. So they invented an awful, awful kludge that modifies
+ // EGL standard behavior, the EGL_EXT_client_extensions extension. EGL 1.4
+ // normally is to return NULL when querying EGL_EXTENSIONS on EGL_NO_DISPLAY,
+ // however, with that extension, it'll return the set of "client extensions",
+ // which may include EGL_EXT_platform_base.
+
+ // Prerequisite: check the platform extension.
+ // If this is either EGL 1.5, or 1.4 with EGL_EXT_client_extensions, then
+ // this must return a valid extension string.
+ const char *exts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (!exts || !gl_check_extension(exts, 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)) {
+ // 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).
+ EGLDisplay (EGLAPIENTRYP GetPlatformDisplay)
+ (EGLenum, void *, const EGLAttrib *) =
+ (void *)eglGetProcAddress("eglGetPlatformDisplay");
+ // (It should be impossible to be NULL, but uh.)
+ if (GetPlatformDisplay)
+ return GetPlatformDisplay(platform, native_display, NULL);
+ }
+
+ // (It should be impossible to be missing, but uh.)
+ if (!gl_check_extension(exts, "EGL_EXT_client_extensions"))
+ return EGL_NO_DISPLAY;
+
+ EGLDisplay (EGLAPIENTRYP GetPlatformDisplayEXT)(EGLenum, void*, const EGLint*)
+ = (void *)eglGetProcAddress("eglGetPlatformDisplayEXT");
+
+ // (It should be impossible to be NULL, but uh.)
+ if (GetPlatformDisplayEXT)
+ return GetPlatformDisplayEXT(platform, native_display, NULL);
+
+ return EGL_NO_DISPLAY;
+}
diff --git a/video/out/opengl/egl_helpers.h b/video/out/opengl/egl_helpers.h
index df489daf0c..bbd274e613 100644
--- a/video/out/opengl/egl_helpers.h
+++ b/video/out/opengl/egl_helpers.h
@@ -29,4 +29,7 @@ bool mpegl_create_context_cb(struct ra_ctx *ctx, EGLDisplay display,
struct GL;
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);
+
#endif