summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/context_x11.c
diff options
context:
space:
mode:
authorNiklas Haas <git@haasn.xyz>2017-09-14 08:04:55 +0200
committerNiklas Haas <git@haasn.xyz>2017-09-21 15:00:55 +0200
commit65979986a923a8f08019b257c3fe72cd5e8ecf68 (patch)
treeb8f4b8c17d583594aef0ca509064f8b2ff7128d4 /video/out/opengl/context_x11.c
parent20f958c9775652c3213588c2a0824f5353276adc (diff)
downloadmpv-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.c358
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,
-};