diff options
author | Niklas Haas <git@haasn.xyz> | 2017-09-14 08:04:55 +0200 |
---|---|---|
committer | Niklas Haas <git@haasn.xyz> | 2017-09-21 15:00:55 +0200 |
commit | 65979986a923a8f08019b257c3fe72cd5e8ecf68 (patch) | |
tree | b8f4b8c17d583594aef0ca509064f8b2ff7128d4 /video/out/opengl/context_x11.c | |
parent | 20f958c9775652c3213588c2a0824f5353276adc (diff) | |
download | mpv-65979986a923a8f08019b257c3fe72cd5e8ecf68.tar.bz2 mpv-65979986a923a8f08019b257c3fe72cd5e8ecf68.tar.xz |
vo_opengl: refactor into vo_gpu
This is done in several steps:
1. refactor MPGLContext -> struct ra_ctx
2. move GL-specific stuff in vo_opengl into opengl/context.c
3. generalize context creation to support other APIs, and add --gpu-api
4. rename all of the --opengl- options that are no longer opengl-specific
5. move all of the stuff from opengl/* that isn't GL-specific into gpu/
(note: opengl/gl_utils.h became opengl/utils.h)
6. rename vo_opengl to vo_gpu
7. to handle window screenshots, the short-term approach was to just add
it to ra_swchain_fns. Long term (and for vulkan) this has to be moved to
ra itself (and vo_gpu altered to compensate), but this was a stop-gap
measure to prevent this commit from getting too big
8. move ra->fns->flush to ra_gl_ctx instead
9. some other minor changes that I've probably already forgotten
Note: This is one half of a major refactor, the other half of which is
provided by rossy's following commit. This commit enables support for
all linux platforms, while his version enables support for all non-linux
platforms.
Note 2: vo_opengl_cb.c also re-uses ra_gl_ctx so it benefits from the
--opengl- options like --opengl-early-flush, --opengl-finish etc. Should
be a strict superset of the old functionality.
Disclaimer: Since I have no way of compiling mpv on all platforms, some
of these ports were done blindly. Specifically, the blind ports included
context_mali_fbdev.c and context_rpi.c. Since they're both based on
egl_helpers, the port should have gone smoothly without any major
changes required. But if somebody complains about a compile error on
those platforms (assuming anybody actually uses them), you know where to
complain.
Diffstat (limited to 'video/out/opengl/context_x11.c')
-rw-r--r-- | video/out/opengl/context_x11.c | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/video/out/opengl/context_x11.c b/video/out/opengl/context_x11.c deleted file mode 100644 index 4d8dac1ea5..0000000000 --- a/video/out/opengl/context_x11.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <X11/Xlib.h> -#include <GL/glx.h> - -// FreeBSD 10.0-CURRENT lacks the GLX_ARB_create_context extension completely -#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB -#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define GLX_CONTEXT_FLAGS_ARB 0x2094 -#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 -#ifndef __APPLE__ -// These are respectively 0x00000001 and 0x00000002 on OSX -#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 -#endif -#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#endif -// GLX_EXT_create_context_es2_profile -#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT -#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 -#endif - -#include "video/out/x11_common.h" -#include "context.h" - -struct glx_context { - XVisualInfo *vinfo; - GLXContext context; - GLXFBConfig fbc; -}; - -static void glx_uninit(MPGLContext *ctx) -{ - struct glx_context *glx_ctx = ctx->priv; - if (glx_ctx->vinfo) - XFree(glx_ctx->vinfo); - if (glx_ctx->context) { - Display *display = ctx->vo->x11->display; - glXMakeCurrent(display, None, NULL); - glXDestroyContext(display, glx_ctx->context); - } - vo_x11_uninit(ctx->vo); -} - -static bool create_context_x11_old(struct MPGLContext *ctx) -{ - struct glx_context *glx_ctx = ctx->priv; - Display *display = ctx->vo->x11->display; - struct vo *vo = ctx->vo; - GL *gl = ctx->gl; - - if (glx_ctx->context) - return true; - - if (!glx_ctx->vinfo) { - MP_FATAL(vo, "Can't create a legacy GLX context without X visual\n"); - return false; - } - - GLXContext new_context = glXCreateContext(display, glx_ctx->vinfo, NULL, - True); - if (!new_context) { - MP_FATAL(vo, "Could not create GLX context!\n"); - return false; - } - - if (!glXMakeCurrent(display, ctx->vo->x11->window, new_context)) { - MP_FATAL(vo, "Could not set GLX context!\n"); - glXDestroyContext(display, new_context); - return false; - } - - const char *glxstr = glXQueryExtensionsString(display, ctx->vo->x11->screen); - - mpgl_load_functions(gl, (void *)glXGetProcAddressARB, glxstr, vo->log); - - glx_ctx->context = new_context; - - return true; -} - -typedef GLXContext (*glXCreateContextAttribsARBProc) - (Display*, GLXFBConfig, GLXContext, Bool, const int*); - -static bool create_context_x11_gl3(struct MPGLContext *ctx, int vo_flags, - int gl_version, bool es) -{ - struct glx_context *glx_ctx = ctx->priv; - struct vo *vo = ctx->vo; - - if (glx_ctx->context) - return true; - - glXCreateContextAttribsARBProc glXCreateContextAttribsARB = - (glXCreateContextAttribsARBProc) - glXGetProcAddressARB((const GLubyte *)"glXCreateContextAttribsARB"); - - const char *glxstr = - glXQueryExtensionsString(vo->x11->display, vo->x11->screen); - bool have_ctx_ext = glxstr && !!strstr(glxstr, "GLX_ARB_create_context"); - - if (!(have_ctx_ext && glXCreateContextAttribsARB)) { - return false; - } - - int ctx_flags = vo_flags & VOFLAG_GL_DEBUG ? GLX_CONTEXT_DEBUG_BIT_ARB : 0; - int profile_mask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - - if (es) { - profile_mask = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; - if (!(glxstr && strstr(glxstr, "GLX_EXT_create_context_es2_profile"))) - return false; - } - - int context_attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version), - GLX_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version), - GLX_CONTEXT_PROFILE_MASK_ARB, profile_mask, - GLX_CONTEXT_FLAGS_ARB, ctx_flags, - None - }; - vo_x11_silence_xlib(1); - GLXContext context = glXCreateContextAttribsARB(vo->x11->display, - glx_ctx->fbc, 0, True, - context_attribs); - vo_x11_silence_xlib(-1); - if (!context) - return false; - - // set context - if (!glXMakeCurrent(vo->x11->display, vo->x11->window, context)) { - MP_FATAL(vo, "Could not set GLX context!\n"); - glXDestroyContext(vo->x11->display, context); - return false; - } - - glx_ctx->context = context; - - mpgl_load_functions(ctx->gl, (void *)glXGetProcAddressARB, glxstr, vo->log); - - return true; -} - -// The GL3/FBC initialization code roughly follows/copies from: -// http://www.opengl.org/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX) -// but also uses some of the old code. - -static GLXFBConfig select_fb_config(struct vo *vo, const int *attribs, int flags) -{ - int fbcount; - GLXFBConfig *fbc = glXChooseFBConfig(vo->x11->display, vo->x11->screen, - attribs, &fbcount); - if (!fbc) - return NULL; - - // The list in fbc is sorted (so that the first element is the best). - GLXFBConfig fbconfig = fbcount > 0 ? fbc[0] : NULL; - - if (flags & VOFLAG_ALPHA) { - for (int n = 0; n < fbcount; n++) { - XVisualInfo *v = glXGetVisualFromFBConfig(vo->x11->display, fbc[n]); - if (v) { - bool is_rgba = vo_x11_is_rgba_visual(v); - XFree(v); - if (is_rgba) { - fbconfig = fbc[n]; - break; - } - } - } - } - - XFree(fbc); - - return fbconfig; -} - -static void set_glx_attrib(int *attribs, int name, int value) -{ - for (int n = 0; attribs[n * 2 + 0] != None; n++) { - if (attribs[n * 2 + 0] == name) { - attribs[n * 2 + 1] = value; - break; - } - } -} - -static int glx_init(struct MPGLContext *ctx, int flags) -{ - struct vo *vo = ctx->vo; - struct glx_context *glx_ctx = ctx->priv; - - if (!vo_x11_init(ctx->vo)) - goto uninit; - - int glx_major, glx_minor; - - if (!glXQueryVersion(vo->x11->display, &glx_major, &glx_minor)) { - MP_ERR(vo, "GLX not found.\n"); - goto uninit; - } - // FBConfigs were added in GLX version 1.3. - if (MPGL_VER(glx_major, glx_minor) < MPGL_VER(1, 3)) { - MP_ERR(vo, "GLX version older than 1.3.\n"); - goto uninit; - } - - int glx_attribs[] = { - GLX_X_RENDERABLE, True, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 0, - GLX_DOUBLEBUFFER, True, - None - }; - GLXFBConfig fbc = NULL; - if (flags & VOFLAG_ALPHA) { - set_glx_attrib(glx_attribs, GLX_ALPHA_SIZE, 1); - fbc = select_fb_config(vo, glx_attribs, flags); - if (!fbc) { - set_glx_attrib(glx_attribs, GLX_ALPHA_SIZE, 0); - flags &= ~VOFLAG_ALPHA; - } - } - if (!fbc) - fbc = select_fb_config(vo, glx_attribs, flags); - if (!fbc) { - MP_ERR(vo, "no GLX support present\n"); - goto uninit; - } - - int fbid = -1; - if (!glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_FBCONFIG_ID, &fbid)) - MP_VERBOSE(vo, "GLX chose FB config with ID 0x%x\n", fbid); - - glx_ctx->fbc = fbc; - glx_ctx->vinfo = glXGetVisualFromFBConfig(vo->x11->display, fbc); - if (glx_ctx->vinfo) { - MP_VERBOSE(vo, "GLX chose visual with ID 0x%x\n", - (int)glx_ctx->vinfo->visualid); - } else { - MP_WARN(vo, "Selected GLX FB config has no associated X visual\n"); - } - - if (!vo_x11_create_vo_window(vo, glx_ctx->vinfo, "gl")) - goto uninit; - - bool success = false; - if (!(flags & VOFLAG_GLES)) { - for (int n = 0; mpgl_preferred_gl_versions[n]; n++) { - int version = mpgl_preferred_gl_versions[n]; - MP_VERBOSE(vo, "Creating OpenGL %d.%d context...\n", - MPGL_VER_P(version)); - if (version >= 300) { - success = create_context_x11_gl3(ctx, flags, version, false); - } else { - success = create_context_x11_old(ctx); - } - if (success) - break; - } - } - if (!success) // try ES - success = create_context_x11_gl3(ctx, flags, 200, true); - if (success && !glXIsDirect(vo->x11->display, glx_ctx->context)) - ctx->gl->mpgl_caps |= MPGL_CAP_SW; - if (!success) - goto uninit; - - return 0; - -uninit: - glx_uninit(ctx); - return -1; -} - -static int glx_init_probe(struct MPGLContext *ctx, int flags) -{ - int r = glx_init(ctx, flags); - if (r >= 0) { - if (!(ctx->gl->mpgl_caps & MPGL_CAP_VDPAU)) { - MP_VERBOSE(ctx->vo, "No vdpau support found - probing more things.\n"); - glx_uninit(ctx); - r = -1; - } - } - return r; -} - -static int glx_reconfig(struct MPGLContext *ctx) -{ - vo_x11_config_vo_window(ctx->vo); - return 0; -} - -static int glx_control(struct MPGLContext *ctx, int *events, int request, - void *arg) -{ - return vo_x11_control(ctx->vo, events, request, arg); -} - -static void glx_swap_buffers(struct MPGLContext *ctx) -{ - glXSwapBuffers(ctx->vo->x11->display, ctx->vo->x11->window); -} - -static void glx_wakeup(struct MPGLContext *ctx) -{ - vo_x11_wakeup(ctx->vo); -} - -static void glx_wait_events(struct MPGLContext *ctx, int64_t until_time_us) -{ - vo_x11_wait_events(ctx->vo, until_time_us); -} - -const struct mpgl_driver mpgl_driver_x11 = { - .name = "x11", - .priv_size = sizeof(struct glx_context), - .init = glx_init, - .reconfig = glx_reconfig, - .swap_buffers = glx_swap_buffers, - .control = glx_control, - .wakeup = glx_wakeup, - .wait_events = glx_wait_events, - .uninit = glx_uninit, -}; - -const struct mpgl_driver mpgl_driver_x11_probe = { - .name = "x11probe", - .priv_size = sizeof(struct glx_context), - .init = glx_init_probe, - .reconfig = glx_reconfig, - .swap_buffers = glx_swap_buffers, - .control = glx_control, - .wakeup = glx_wakeup, - .wait_events = glx_wait_events, - .uninit = glx_uninit, -}; |