summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-09-14 10:05:00 +0200
committerwm4 <wm4@nowhere>2016-09-14 10:19:09 +0200
commitd2e8bc449986e012f257249a996386bd323febd0 (patch)
treeef63019837e4eda38b7bafb6020cb88512627247
parentc48bd0ef183c7ae4c2893495ac9cbca08c06bbae (diff)
downloadmpv-d2e8bc449986e012f257249a996386bd323febd0.tar.bz2
mpv-d2e8bc449986e012f257249a996386bd323febd0.tar.xz
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.
-rw-r--r--video/out/opengl/egl_helpers.c84
1 files changed, 65 insertions, 19 deletions
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
- };
-
- if (!es) {
- context_attributes[2] = EGL_CONTEXT_OPENGL_PROFILE_MASK;
- context_attributes[3] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
+ EGLContext *ctx = NULL;
+
+ 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;
}