From 6dc9280b580835d37fa8a8664b6bc142254ce1a1 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 13 Sep 2016 15:38:51 +0200 Subject: vo_opengl: factor some EGL context creation code Add a function to egl_helpers.c for creating an EGL context and make context_x11egl.c use it. This is meant to be generic, and should work with other windowing APIs as well. The other EGL-using code in mpv can be switched to it. --- video/out/opengl/context.c | 2 + video/out/opengl/context.h | 1 + video/out/opengl/context_x11egl.c | 90 +++++++----------------------------- video/out/opengl/egl_helpers.c | 96 +++++++++++++++++++++++++++++++++++++++ video/out/opengl/egl_helpers.h | 7 +++ 5 files changed, 122 insertions(+), 74 deletions(-) (limited to 'video') diff --git a/video/out/opengl/context.c b/video/out/opengl/context.c index 21e6d6799e..a8058fb18c 100644 --- a/video/out/opengl/context.c +++ b/video/out/opengl/context.c @@ -155,6 +155,8 @@ static MPGLContext *init_backend(struct vo *vo, const struct mpgl_driver *driver .vo = vo, .driver = driver, }; + if (probing) + vo_flags |= VOFLAG_PROBING; bool old_probing = vo->probing; vo->probing = probing; // hack; kill it once backends are separate MP_VERBOSE(vo, "Initializing OpenGL backend '%s'\n", ctx->driver->name); diff --git a/video/out/opengl/context.h b/video/out/opengl/context.h index 505c51168a..d0588ddbd9 100644 --- a/video/out/opengl/context.h +++ b/video/out/opengl/context.h @@ -33,6 +33,7 @@ enum { VOFLAG_ALPHA = 1 << 3, // Hint to request alpha framebuffer VOFLAG_SW = 1 << 4, // Hint to accept a software GL renderer VOFLAG_ANGLE_DCOMP = 1 << 5, // Whether DirectComposition is allowed + VOFLAG_PROBING = 1 << 6, // The backend is being auto-probed. }; extern const int mpgl_preferred_gl_versions[]; diff --git a/video/out/opengl/context_x11egl.c b/video/out/opengl/context_x11egl.c index aea388b9a2..7a9e4d31fc 100644 --- a/video/out/opengl/context_x11egl.c +++ b/video/out/opengl/context_x11egl.c @@ -49,94 +49,24 @@ static void mpegl_uninit(MPGLContext *ctx) vo_x11_uninit(ctx->vo); } -static EGLConfig select_fb_config_egl(struct MPGLContext *ctx, bool es) -{ - struct priv *p = ctx->priv; - - EGLint attributes[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_DEPTH_SIZE, 0, - EGL_RENDERABLE_TYPE, es ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT, - EGL_NONE - }; - - EGLint config_count; - EGLConfig config; - - eglChooseConfig(p->egl_display, attributes, &config, 1, &config_count); - - if (!config_count) { - MP_FATAL(ctx->vo, "Could not find EGL configuration!\n"); - return NULL; - } - - return config; -} - -static bool create_context_egl(MPGLContext *ctx, EGLConfig config, - EGLNativeWindowType window, bool es) -{ - struct priv *p = ctx->priv; - - 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; - } - - p->egl_surface = eglCreateWindowSurface(p->egl_display, config, window, NULL); - - if (p->egl_surface == EGL_NO_SURFACE) { - MP_FATAL(ctx->vo, "Could not create EGL surface!\n"); - return false; - } - - p->egl_context = eglCreateContext(p->egl_display, config, - EGL_NO_CONTEXT, context_attributes); - - if (p->egl_context == EGL_NO_CONTEXT) { - MP_FATAL(ctx->vo, "Could not create EGL context!\n"); - return false; - } - - eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, - p->egl_context); - - return true; -} - static int mpegl_init(struct MPGLContext *ctx, int flags) { struct priv *p = ctx->priv; struct vo *vo = ctx->vo; - bool es = flags & VOFLAG_GLES; int msgl = vo->probing ? MSGL_V : MSGL_FATAL; if (!vo_x11_init(vo)) goto uninit; - if (!eglBindAPI(es ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) { - mp_msg(vo->log, msgl, "Could not bind API (%s).\n", es ? "GLES" : "GL"); - goto uninit; - } - p->egl_display = eglGetDisplay(vo->x11->display); if (!eglInitialize(p->egl_display, NULL, NULL)) { mp_msg(vo->log, msgl, "Could not initialize EGL.\n"); goto uninit; } - EGLConfig config = select_fb_config_egl(ctx, es); - if (!config) + EGLConfig config; + if (!mpegl_create_context(p->egl_display, vo->log, flags, &p->egl_context, + &config)) goto uninit; int vID, n; @@ -156,8 +86,20 @@ static int mpegl_init(struct MPGLContext *ctx, int flags) XFree(vi); - if (!create_context_egl(ctx, config, (EGLNativeWindowType)vo->x11->window, es)) + p->egl_surface = eglCreateWindowSurface(p->egl_display, config, + (EGLNativeWindowType)vo->x11->window, NULL); + + if (p->egl_surface == EGL_NO_SURFACE) { + MP_FATAL(ctx->vo, "Could not create EGL surface!\n"); goto uninit; + } + + if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, + p->egl_context)) + { + MP_FATAL(ctx->vo, "Could not make context current!\n"); + goto uninit; + } const char *egl_exts = eglQueryString(p->egl_display, EGL_EXTENSIONS); diff --git a/video/out/opengl/egl_helpers.c b/video/out/opengl/egl_helpers.c index 7e236f1da9..b06e6a79af 100644 --- a/video/out/opengl/egl_helpers.c +++ b/video/out/opengl/egl_helpers.c @@ -15,6 +15,102 @@ * License along with mpv. If not, see . */ +#include "common/common.h" + #include "egl_helpers.h" #include "common.h" +#include "context.h" + +// EGL 1.5 +#ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK +#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 +#endif + +static bool create_context(EGLDisplay display, struct mp_log *log, int msgl, + int vo_flags, + 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)) { + mp_msg(log, msgl, "Could not bind API!\n"); + return false; + } + + EGLint attributes[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + 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_NONE + }; + + EGLint config_count; + EGLConfig config; + + eglChooseConfig(display, attributes, &config, 1, &config_count); + + if (!config_count) { + mp_msg(log, msgl, "Could not find EGL configuration!\n"); + 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 = eglCreateContext(display, config, + EGL_NO_CONTEXT, context_attributes); + + if (!ctx) { + mp_msg(log, msgl, "Could not create EGL context!\n"); + return false; + } + + *out_context = ctx; + *out_config = config; + return true; +} + +// Create a context and return it and the config it was created with. If it +// returns false, the out_* pointers are set to NULL. +// vo_flags is a combination of VOFLAG_* values. +bool mpegl_create_context(EGLDisplay display, struct mp_log *log, int vo_flags, + EGLContext *out_context, EGLConfig *out_config) +{ + *out_context = NULL; + *out_config = NULL; + + int clean_flags = vo_flags & ~(unsigned)(VOFLAG_GLES | VOFLAG_NO_GLES); + int msgl = vo_flags & VOFLAG_PROBING ? MSGL_V : MSGL_FATAL; + + if (!(vo_flags & VOFLAG_GLES)) { + if (create_context(display, log, msgl, clean_flags, + out_context, out_config)) + return true; + } + + if (!(vo_flags & VOFLAG_NO_GLES)) { + if (create_context(display, log, msgl, clean_flags | VOFLAG_GLES, + out_context, out_config)) + return true; + } + + mp_msg(log, msgl, "Could not create a GL context.\n"); + return false; +} diff --git a/video/out/opengl/egl_helpers.h b/video/out/opengl/egl_helpers.h index 3806ef1d35..04197493f3 100644 --- a/video/out/opengl/egl_helpers.h +++ b/video/out/opengl/egl_helpers.h @@ -1,7 +1,14 @@ #ifndef MP_GL_EGL_HELPERS_H #define MP_GL_EGL_HELPERS_H +#include + #include #include +struct mp_log; + +bool mpegl_create_context(EGLDisplay display, struct mp_log *log, int vo_flags, + EGLContext *out_context, EGLConfig *out_config); + #endif -- cgit v1.2.3