vo_opengl: EGL: better desktop-GL context creation

Stops Mesa from restricting us to OpenGL 3.0. It also tries to create
GLES 3 contexts for drivers which do not just return a higher context
when requesting GLES 2.

I don't know whether this code is a good or bad idea. A not-so-good
aspect is that we don't check for EGL 1.5 (or 1.4 extensions) for some
of the more advanced context attributes. But EGL implementations should
be able to tolerate it and return an error, and then we'd use the
fallback.
This commit is contained in:
wm4 2016-09-14 10:05:00 +02:00
parent c48bd0ef18
commit d2e8bc4499
1 changed files with 64 additions and 18 deletions

View File

@ -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;
}