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) { MP_VERBOSE(vo, "Could not create GL3 context. Retrying with legacy context.\n"); 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; }
static bool create_context_x11_gl3(struct MPGLContext *ctx, bool debug) { 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 = ""; const char *(*glXExtStr)(Display *, int) = mp_getdladdr("glXQueryExtensionsString"); if (glXExtStr) glxstr = glXExtStr(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 gl_version = ctx->requested_gl_version; 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, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB, debug ? GLX_CONTEXT_DEBUG_BIT_ARB : 0, None }; GLXContext context = glXCreateContextAttribsARB(vo->x11->display, glx_ctx->fbc, 0, True, context_attribs); if (!context) { MP_ERR(vo, "Could not create GL3 context. Retrying with legacy context.\n"); 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 *)glXGetProcAddress, glxstr, vo->log); if (!glXIsDirect(vo->x11->display, context)) ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW; return true; }
static bool egl_create_context(struct vo_wayland_state *wl, MPGLContext *ctx, bool enable_alpha) { EGLint major, minor, n; GL *gl = ctx->gl; const char *eglstr = ""; if (!(wl->egl_context.egl.dpy = eglGetDisplay(wl->display.display))) return false; EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, enable_alpha, EGL_DEPTH_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE }; /* major and minor here returns the supported EGL version (e.g.: 1.4) */ if (eglInitialize(wl->egl_context.egl.dpy, &major, &minor) != EGL_TRUE) return false; MP_VERBOSE(wl, "EGL version %d.%d\n", major, minor); EGLint context_attribs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, MPGL_VER_GET_MAJOR(ctx->requested_gl_version), EGL_NONE }; if (eglBindAPI(EGL_OPENGL_API) != EGL_TRUE) return false; eglChooseConfig(wl->egl_context.egl.dpy, config_attribs, &wl->egl_context.egl.conf, 1, &n); wl->egl_context.egl.ctx = eglCreateContext(wl->egl_context.egl.dpy, wl->egl_context.egl.conf, EGL_NO_CONTEXT, context_attribs); if (!wl->egl_context.egl.ctx) { /* fallback to any GL version */ MP_WARN(wl, "can't create context for requested OpenGL version: " "fall back to any version available\n"); context_attribs[0] = EGL_NONE; wl->egl_context.egl.ctx = eglCreateContext(wl->egl_context.egl.dpy, wl->egl_context.egl.conf, EGL_NO_CONTEXT, context_attribs); if (!wl->egl_context.egl.ctx) return false; } eglMakeCurrent(wl->egl_context.egl.dpy, NULL, NULL, wl->egl_context.egl.ctx); eglstr = eglQueryString(wl->egl_context.egl.dpy, EGL_EXTENSIONS); mpgl_load_functions(gl, (void*(*)(const GLubyte*))eglGetProcAddress, eglstr, wl->log); if (!gl->BindProgram) mpgl_load_functions(gl, NULL, eglstr, wl->log); return true; }
static bool create_context_w32_gl3(struct MPGLContext *ctx) { struct w32_context *w32_ctx = ctx->priv; HGLRC *context = &w32_ctx->context; if (*context) // reuse existing context return true; // not reusing it breaks gl3! HWND win = ctx->vo->w32->window; HDC windc = GetDC(win); HGLRC new_context = 0; new_context = wglCreateContext(windc); if (!new_context) { MP_FATAL(ctx->vo, "Could not create GL context!\n"); return false; } // set context if (!wglMakeCurrent(windc, new_context)) { MP_FATAL(ctx->vo, "Could not set GL context!\n"); goto out; } const char *(GLAPIENTRY *wglGetExtensionsStringARB)(HDC hdc) = w32gpa((const GLubyte*)"wglGetExtensionsStringARB"); if (!wglGetExtensionsStringARB) goto unsupported; const char *wgl_exts = wglGetExtensionsStringARB(windc); if (!strstr(wgl_exts, "WGL_ARB_create_context")) goto unsupported; HGLRC (GLAPIENTRY *wglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext, const int *attribList) = w32gpa((const GLubyte*)"wglCreateContextAttribsARB"); if (!wglCreateContextAttribsARB) goto unsupported; int gl_version = ctx->requested_gl_version; int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version), WGL_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version), WGL_CONTEXT_FLAGS_ARB, 0, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0 }; *context = wglCreateContextAttribsARB(windc, 0, attribs); if (! *context) { // NVidia, instead of ignoring WGL_CONTEXT_FLAGS_ARB, will error out if // it's present on pre-3.2 contexts. // Remove it from attribs and retry the context creation. attribs[6] = attribs[7] = 0; *context = wglCreateContextAttribsARB(windc, 0, attribs); } if (! *context) { int err = GetLastError(); MP_FATAL(ctx->vo, "Could not create an OpenGL 3.x context: error 0x%x\n", err); goto out; } wglMakeCurrent(NULL, NULL); wglDeleteContext(new_context); if (!wglMakeCurrent(windc, *context)) { MP_FATAL(ctx->vo, "Could not set GL3 context!\n"); wglDeleteContext(*context); return false; } /* update function pointers */ mpgl_load_functions(ctx->gl, w32gpa, NULL, ctx->vo->log); int pfmt = GetPixelFormat(windc); PIXELFORMATDESCRIPTOR pfd; if (DescribePixelFormat(windc, pfmt, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) { ctx->depth_r = pfd.cRedBits; ctx->depth_g = pfd.cGreenBits; ctx->depth_b = pfd.cBlueBits; } return true; unsupported: MP_ERR(ctx->vo, "The current OpenGL implementation does not support OpenGL 3.x \n"); out: wglDeleteContext(new_context); return false; }
static bool create_context_w32_gl3(struct MPGLContext *ctx) { struct w32_context *w32_ctx = ctx->priv; HDC windc = w32_ctx->hdc; HGLRC context = 0; // A legacy context is needed to get access to the new functions. HGLRC legacy_context = wglCreateContext(windc); if (!legacy_context) { MP_FATAL(ctx->vo, "Could not create GL context!\n"); return false; } // set context if (!wglMakeCurrent(windc, legacy_context)) { MP_FATAL(ctx->vo, "Could not set GL context!\n"); goto out; } const char *(GLAPIENTRY *wglGetExtensionsStringARB)(HDC hdc) = w32gpa((const GLubyte*)"wglGetExtensionsStringARB"); if (!wglGetExtensionsStringARB) goto unsupported; const char *wgl_exts = wglGetExtensionsStringARB(windc); if (!strstr(wgl_exts, "WGL_ARB_create_context")) goto unsupported; HGLRC (GLAPIENTRY *wglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext, const int *attribList) = w32gpa((const GLubyte*)"wglCreateContextAttribsARB"); if (!wglCreateContextAttribsARB) goto unsupported; int gl_version = ctx->requested_gl_version; int attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, MPGL_VER_GET_MAJOR(gl_version), WGL_CONTEXT_MINOR_VERSION_ARB, MPGL_VER_GET_MINOR(gl_version), WGL_CONTEXT_FLAGS_ARB, 0, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0 }; context = wglCreateContextAttribsARB(windc, 0, attribs); if (!context) { // NVidia, instead of ignoring WGL_CONTEXT_FLAGS_ARB, will error out if // it's present on pre-3.2 contexts. // Remove it from attribs and retry the context creation. attribs[6] = attribs[7] = 0; context = wglCreateContextAttribsARB(windc, 0, attribs); } if (!context) { int err = GetLastError(); MP_FATAL(ctx->vo, "Could not create an OpenGL 3.x context: error 0x%x\n", err); goto out; } wglMakeCurrent(windc, NULL); wglDeleteContext(legacy_context); if (!wglMakeCurrent(windc, context)) { MP_FATAL(ctx->vo, "Could not set GL3 context!\n"); wglDeleteContext(context); return false; } w32_ctx->context = context; /* update function pointers */ mpgl_load_functions(ctx->gl, w32gpa, NULL, ctx->vo->log); return true; unsupported: MP_ERR(ctx->vo, "The OpenGL driver does not support OpenGL 3.x \n"); out: wglMakeCurrent(windc, NULL); wglDeleteContext(legacy_context); return false; }
static bool egl_create_context(struct vo_wayland_state *wl, struct egl_context *egl_ctx, MPGLContext *ctx, bool enable_alpha) { EGLint major, minor, n; GL *gl = ctx->gl; const char *eglstr = ""; if (!(egl_ctx->egl.dpy = eglGetDisplay(wl->display->display))) return false; EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, enable_alpha, EGL_DEPTH_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE }; /* major and minor here returns the supported EGL version (e.g.: 1.4) */ if (eglInitialize(egl_ctx->egl.dpy, &major, &minor) != EGL_TRUE) return false; EGLint context_attribs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, MPGL_VER_GET_MAJOR(ctx->requested_gl_version), /* EGL_CONTEXT_MINOR_VERSION_KHR, */ /* MPGL_VER_GET_MINOR(ctx->requested_gl_version), */ /* EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, 0, */ /* Segfaults on anything else than the major version */ EGL_NONE }; if (eglBindAPI(EGL_OPENGL_API) != EGL_TRUE) return false; eglChooseConfig(egl_ctx->egl.dpy, config_attribs, &egl_ctx->egl.conf, 1, &n); egl_ctx->egl.ctx = eglCreateContext(egl_ctx->egl.dpy, egl_ctx->egl.conf, EGL_NO_CONTEXT, context_attribs); if (!egl_ctx->egl.ctx) return false; eglMakeCurrent(egl_ctx->egl.dpy, NULL, NULL, egl_ctx->egl.ctx); eglstr = eglQueryString(egl_ctx->egl.dpy, EGL_EXTENSIONS); mpgl_load_functions(gl, (void*(*)(const GLubyte*))eglGetProcAddress, eglstr); if (!gl->BindProgram) mpgl_load_functions(gl, NULL, eglstr); return true; }