diff --git a/video/out/opengl/egl_helpers.c b/video/out/opengl/egl_helpers.c index e96ae93b06..a5ffd5cf95 100644 --- a/video/out/opengl/egl_helpers.c +++ b/video/out/opengl/egl_helpers.c @@ -23,23 +23,43 @@ // EGL 1.5 #ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK +#define EGL_CONTEXT_MAJOR_VERSION 0x3098 +#define EGL_CONTEXT_MINOR_VERSION 0x30FB #define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1 +#define EGL_OPENGL_ES3_BIT 0x00000040 #endif static bool create_context(EGLDisplay display, struct mp_log *log, int msgl, - int vo_flags, + int vo_flags, bool es3, EGLContext *out_context, EGLConfig *out_config) { bool es = vo_flags & VOFLAG_GLES; - mp_msg(log, MSGL_V, "Trying to create %s context.\n", es ? "GLES" : "GL"); - if (!eglBindAPI(es ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) { + EGLenum api = EGL_OPENGL_API; + EGLint rend = EGL_OPENGL_BIT; + const char *name = "Desktop OpenGL"; + if (es) { + api = EGL_OPENGL_ES_API; + rend = EGL_OPENGL_ES2_BIT; + name = "GLES 2.0"; + } + if (es3) { + api = EGL_OPENGL_ES_API; + rend = EGL_OPENGL_ES3_BIT; + name = "GLES 3.x"; + } + + mp_msg(log, MSGL_V, "Trying to create %s context.\n", name); + + if (!eglBindAPI(api)) { mp_msg(log, MSGL_V, "Could not bind API!\n"); return false; } + EGLint attributes[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 1, @@ -47,7 +67,7 @@ static bool create_context(EGLDisplay display, struct mp_log *log, int msgl, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, (vo_flags & VOFLAG_ALPHA ) ? 1 : 0, EGL_DEPTH_SIZE, 0, - EGL_RENDERABLE_TYPE, es ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT, + EGL_RENDERABLE_TYPE, rend, EGL_NONE }; @@ -61,21 +81,40 @@ static bool create_context(EGLDisplay display, struct mp_log *log, int msgl, return false; } - EGLint context_attributes[] = { - // aka EGL_CONTEXT_MAJOR_VERSION_KHR - EGL_CONTEXT_CLIENT_VERSION, es ? 2 : 3, - EGL_NONE, EGL_NONE, - EGL_NONE - }; + EGLContext *ctx = NULL; - if (!es) { - context_attributes[2] = EGL_CONTEXT_OPENGL_PROFILE_MASK; - context_attributes[3] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT; + if (es) { + EGLint attrs[] = { + EGL_CONTEXT_CLIENT_VERSION, es3 ? 3 : 2, + EGL_NONE + }; + + ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, attrs); + } else { + for (int n = 0; mpgl_preferred_gl_versions[n]; n++) { + int ver = mpgl_preferred_gl_versions[n]; + + EGLint attrs[] = { + EGL_CONTEXT_MAJOR_VERSION, MPGL_VER_GET_MAJOR(ver), + EGL_CONTEXT_MINOR_VERSION, MPGL_VER_GET_MINOR(ver), + EGL_CONTEXT_OPENGL_PROFILE_MASK, + ver >= 320 ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT : 0, + EGL_NONE + }; + + ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, attrs); + if (ctx) + break; + } + + if (!ctx) { + // Fallback for EGL 1.4 without EGL_KHR_create_context. + EGLint attrs[] = { EGL_NONE }; + + ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, attrs); + } } - EGLContext *ctx = eglCreateContext(display, config, - EGL_NO_CONTEXT, context_attributes); - if (!ctx) { mp_msg(log, msgl, "Could not create EGL context!\n"); return false; @@ -99,13 +138,20 @@ bool mpegl_create_context(EGLDisplay display, struct mp_log *log, int vo_flags, int msgl = vo_flags & VOFLAG_PROBING ? MSGL_V : MSGL_FATAL; if (!(vo_flags & VOFLAG_GLES)) { - if (create_context(display, log, msgl, clean_flags, + // Desktop OpenGL + if (create_context(display, log, msgl, clean_flags, false, out_context, out_config)) return true; } if (!(vo_flags & VOFLAG_NO_GLES)) { - if (create_context(display, log, msgl, clean_flags | VOFLAG_GLES, + // ES 3.x + if (create_context(display, log, msgl, clean_flags | VOFLAG_GLES, true, + out_context, out_config)) + return true; + + // ES 2.0 + if (create_context(display, log, msgl, clean_flags | VOFLAG_GLES, false, out_context, out_config)) return true; }