static int drm_egl_init(struct MPGLContext *ctx, int flags) { struct priv *p = ctx->priv; p->kms = NULL; p->old_crtc = NULL; p->gbm.surface = NULL; p->gbm.device = NULL; p->active = false; p->waiting_for_flip = false; p->ev.version = DRM_EVENT_CONTEXT_VERSION; p->ev.page_flip_handler = page_flipped; p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, ctx->vo->log); if (p->vt_switcher_active) { vt_switcher_acquire(&p->vt_switcher, acquire_vt, ctx); vt_switcher_release(&p->vt_switcher, release_vt, ctx); } else { MP_WARN(ctx->vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n"); } MP_VERBOSE(ctx->vo, "Initializing KMS\n"); p->kms = kms_create(ctx->vo->log); if (!p->kms) { MP_ERR(ctx->vo, "Failed to create KMS.\n"); return -1; } // TODO: arguments should be configurable if (!kms_setup(p->kms, "/dev/dri/card0", -1, 0)) { MP_ERR(ctx->vo, "Failed to configure KMS.\n"); return -1; } if (!init_gbm(ctx)) { MP_ERR(ctx->vo, "Failed to setup GBM.\n"); return -1; } if (!init_egl(ctx, flags & VOFLAG_GLES)) { MP_ERR(ctx->vo, "Failed to setup EGL.\n"); return -1; } if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface, p->egl.context)) { MP_ERR(ctx->vo, "Failed to make context current.\n"); return -1; } const char *egl_exts = eglQueryString(p->egl.display, EGL_EXTENSIONS); void *(*gpa)(const GLubyte*) = (void *(*)(const GLubyte*))eglGetProcAddress; mpgl_load_functions(ctx->gl, gpa, egl_exts, ctx->vo->log); // required by gbm_surface_lock_front_buffer eglSwapBuffers(p->egl.display, p->egl.surface); MP_VERBOSE(ctx->vo, "Preparing framebuffer\n"); p->gbm.bo = gbm_surface_lock_front_buffer(p->gbm.surface); if (!p->gbm.bo) { MP_ERR(ctx->vo, "Failed to lock GBM surface.\n"); return -1; } update_framebuffer_from_bo(ctx, p->gbm.bo); if (!p->fb.id) { MP_ERR(ctx->vo, "Failed to create framebuffer.\n"); return -1; } if (!crtc_setup(ctx)) { MP_ERR( ctx->vo, "Failed to set CRTC for connector %u: %s\n", p->kms->connector->connector_id, mp_strerror(errno)); return -1; } return 0; }
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; 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; } void *(*getProcAddress)(const GLubyte *); getProcAddress = mp_getdladdr("glXGetProcAddress"); if (!getProcAddress) getProcAddress = mp_getdladdr("glXGetProcAddressARB"); const char *glxstr = ""; const char *(*glXExtStr)(Display *, int) = mp_getdladdr("glXQueryExtensionsString"); if (glXExtStr) glxstr = glXExtStr(display, ctx->vo->x11->screen); mpgl_load_functions(gl, getProcAddress, glxstr, vo->log); if (!gl->GenPrograms && gl->GetString && gl->version < MPGL_VER(3, 0) && strstr(gl->GetString(GL_EXTENSIONS), "GL_ARB_vertex_program")) { MP_WARN(vo, "Broken glXGetProcAddress detected, trying workaround\n"); mpgl_load_functions(gl, NULL, glxstr, vo->log); } glx_ctx->context = new_context; if (!glXIsDirect(vo->x11->display, new_context)) ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW; return true; }
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_gl_context(struct MPGLContext *ctx) { struct cgl_context *p = ctx->priv; CGLError err; CGLOpenGLProfile gl_versions[] = { kCGLOGLPVersion_3_2_Core, kCGLOGLPVersion_Legacy, }; for (int n = 0; n < MP_ARRAY_SIZE(gl_versions); n++) { err = test_gl_version(ctx->vo, &p->ctx, &p->pix, gl_versions[n]); if (err == kCGLNoError) break; } if (err != kCGLNoError) { MP_FATAL(ctx->vo, "error creating CGL context: %s (%d)\n", CGLErrorString(err), err); return false; } vo_cocoa_set_opengl_ctx(ctx->vo, p->ctx); CGLSetCurrentContext(p->ctx); ctx->depth_r = ctx->depth_g = ctx->depth_b = cgl_color_size(ctx); mpgl_load_functions(ctx->gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log); CGLReleasePixelFormat(p->pix); return true; }
int mp_egl_rpi_init(struct mp_egl_rpi *p, DISPMANX_ELEMENT_HANDLE_T window, int w, int h) { p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!eglInitialize(p->egl_display, NULL, NULL)) { MP_FATAL(p, "EGL failed to initialize.\n"); goto fail; } eglBindAPI(EGL_OPENGL_ES_API); EGLConfig config = select_fb_config_egl(p); if (!config) goto fail; p->egl_window = (EGL_DISPMANX_WINDOW_T){ .element = window, .width = w, .height = h, }; p->egl_surface = eglCreateWindowSurface(p->egl_display, config, &p->egl_window, NULL); if (p->egl_surface == EGL_NO_SURFACE) { MP_FATAL(p, "Could not create EGL surface!\n"); goto fail; } EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; p->egl_context = eglCreateContext(p->egl_display, config, EGL_NO_CONTEXT, context_attributes); if (p->egl_context == EGL_NO_CONTEXT) { MP_FATAL(p, "Could not create EGL context!\n"); goto fail; } eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface, p->egl_context); p->gl = talloc_zero(NULL, struct GL); const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS); mpgl_load_functions(p->gl, get_proc_address, exts, p->log); if (!p->gl->version && !p->gl->es) goto fail; return 0; fail: mp_egl_rpi_destroy(p); return -1; }
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 config_window_cocoa(struct MPGLContext *ctx, int flags) { int rv = vo_cocoa_config_window(ctx->vo, flags, ctx->requested_gl_version >= MPGL_VER(3, 0)); if (rv != 0) return false; mpgl_load_functions(ctx->gl, (void *)vo_cocoa_glgetaddr, NULL, ctx->vo->log); ctx->depth_r = vo_cocoa_cgl_color_size(ctx->vo); ctx->depth_g = vo_cocoa_cgl_color_size(ctx->vo); ctx->depth_b = vo_cocoa_cgl_color_size(ctx->vo); if (!ctx->gl->SwapInterval) ctx->gl->SwapInterval = vo_cocoa_swap_interval; vo_cocoa_register_gl_clear_callback(ctx->vo, ctx->gl, gl_clear); return true; }
static bool create_context_w32_old(struct MPGLContext *ctx) { GL *gl = ctx->gl; struct w32_context *w32_ctx = ctx->priv; HGLRC *context = &w32_ctx->context; if (*context) { gl->Finish(); // supposedly to prevent flickering return true; } HWND win = ctx->vo->w32->window; HDC windc = GetDC(win); bool res = false; HGLRC new_context = wglCreateContext(windc); if (!new_context) { MP_FATAL(ctx->vo, "Could not create GL context!\n"); goto out; } if (!wglMakeCurrent(windc, new_context)) { MP_FATAL(ctx->vo, "Could not set GL context!\n"); wglDeleteContext(new_context); goto out; } *context = new_context; mpgl_load_functions(ctx->gl, w32gpa, NULL, ctx->vo->log); res = true; out: ReleaseDC(win, windc); return res; }
static bool create_context_w32_old(struct MPGLContext *ctx) { struct w32_context *w32_ctx = ctx->priv; HDC windc = w32_ctx->hdc; bool res = false; HGLRC context = wglCreateContext(windc); if (!context) { MP_FATAL(ctx->vo, "Could not create GL context!\n"); return res; } if (!wglMakeCurrent(windc, context)) { MP_FATAL(ctx->vo, "Could not set GL context!\n"); wglDeleteContext(context); return res; } w32_ctx->context = context; mpgl_load_functions(ctx->gl, w32gpa, NULL, ctx->vo->log); return true; }
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; }
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; }
static int angle_init(struct MPGLContext *ctx, int flags) { struct priv *p = ctx->priv; struct vo *vo = ctx->vo; if (!angle_load()) { MP_VERBOSE(vo, "Failed to load LIBEGL.DLL\n"); goto fail; } if (!vo_w32_init(vo)) goto fail; HDC dc = GetDC(vo_w32_hwnd(vo)); if (!dc) { MP_FATAL(vo, "Couldn't get DC\n"); goto fail; } PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); if (!eglGetPlatformDisplayEXT) { MP_FATAL(vo, "Missing EGL_EXT_platform_base\n"); goto fail; } EGLint d3d_types[] = {EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE}; EGLint d3d_dev_types[] = {EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE}; for (int i = 0; i < MP_ARRAY_SIZE(d3d_types); i++) { EGLint display_attributes[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, d3d_types[i], EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, d3d_dev_types[i], EGL_NONE, }; p->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, display_attributes); if (p->egl_display == EGL_NO_DISPLAY) continue; if (!eglInitialize(p->egl_display, NULL, NULL)) { p->egl_display = EGL_NO_DISPLAY; continue; } if (d3d_dev_types[i] == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE) show_sw_adapter_msg(ctx); break; } if (p->egl_display == EGL_NO_DISPLAY) { MP_FATAL(vo, "Couldn't get display\n"); goto fail; } const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS); if (exts) MP_DBG(ctx->vo, "EGL extensions: %s\n", exts); eglBindAPI(EGL_OPENGL_ES_API); if (eglGetError() != EGL_SUCCESS) { MP_FATAL(vo, "Couldn't bind GLES API\n"); goto fail; } EGLConfig config = select_fb_config_egl(ctx); if (!config) goto fail; int window_attribs_len = 0; EGLint *window_attribs = NULL; EGLint flip_val; if (eglGetConfigAttrib(p->egl_display, config, EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, &flip_val)) { if (flip_val == EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) { MP_TARRAY_APPEND(NULL, window_attribs, window_attribs_len, EGL_SURFACE_ORIENTATION_ANGLE); MP_TARRAY_APPEND(NULL, window_attribs, window_attribs_len, EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE); ctx->flip_v = true; MP_VERBOSE(vo, "Rendering flipped.\n"); } } // EGL_DIRECT_COMPOSITION_ANGLE enables the use of flip-mode present, which // avoids a copy of the video image and lowers vsync jitter, though the // extension is only present on Windows 8 and up. if (strstr(exts, "EGL_ANGLE_direct_composition")) { MP_TARRAY_APPEND(NULL, window_attribs, window_attribs_len, EGL_DIRECT_COMPOSITION_ANGLE); MP_TARRAY_APPEND(NULL, window_attribs, window_attribs_len, EGL_TRUE); MP_VERBOSE(vo, "Using DirectComposition.\n"); } MP_TARRAY_APPEND(NULL, window_attribs, window_attribs_len, EGL_NONE); p->egl_surface = eglCreateWindowSurface(p->egl_display, config, vo_w32_hwnd(vo), window_attribs); talloc_free(window_attribs); if (p->egl_surface == EGL_NO_SURFACE) { MP_FATAL(ctx->vo, "Could not create EGL surface!\n"); goto fail; } if (!(!p->use_es2 && create_context_egl(ctx, config, 3)) && !create_context_egl(ctx, config, 2)) { MP_FATAL(ctx->vo, "Could not create EGL context!\n"); goto fail; } // Configure the underlying Direct3D device d3d_init(ctx); if (strstr(exts, "EGL_NV_post_sub_buffer")) { p->eglPostSubBufferNV = (PFNEGLPOSTSUBBUFFERNVPROC)eglGetProcAddress("eglPostSubBufferNV"); } mpgl_load_functions(ctx->gl, get_proc_address, NULL, vo->log); return 0; fail: angle_uninit(ctx); return -1; }
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; 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 attribs[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 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 int angle_init(struct MPGLContext *ctx, int flags) { struct priv *p = ctx->priv; struct vo *vo = ctx->vo; if (!vo_w32_init(vo)) goto fail; HDC dc = GetDC(vo_w32_hwnd(vo)); if (!dc) { MP_FATAL(vo, "Couldn't get DC\n"); goto fail; } PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); if (!eglGetPlatformDisplayEXT) { MP_FATAL(vo, "Missing EGL_EXT_platform_base\n"); goto fail; } EGLint d3d_types[] = {EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE}; for (int i = 0; i < MP_ARRAY_SIZE(d3d_types); i++) { EGLint display_attributes[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, d3d_types[i], EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, EGL_NONE, }; p->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, display_attributes); if (p->egl_display != EGL_NO_DISPLAY) break; } if (p->egl_display == EGL_NO_DISPLAY) { MP_FATAL(vo, "Couldn't get display\n"); goto fail; } if (!eglInitialize(p->egl_display, NULL, NULL)) { MP_FATAL(vo, "Couldn't initialize EGL\n"); goto fail; } eglBindAPI(EGL_OPENGL_ES_API); if (eglGetError() != EGL_SUCCESS) { MP_FATAL(vo, "Couldn't bind GLES API\n"); goto fail; } EGLConfig config = select_fb_config_egl(ctx); if (!config) goto fail; p->egl_surface = eglCreateWindowSurface(p->egl_display, config, vo_w32_hwnd(vo), NULL); if (p->egl_surface == EGL_NO_SURFACE) { MP_FATAL(ctx->vo, "Could not create EGL surface!\n"); goto fail; } if (!create_context_egl(ctx, config, 3) && !create_context_egl(ctx, config, 2)) { MP_FATAL(ctx->vo, "Could not create EGL context!\n"); goto fail; } mpgl_load_functions(ctx->gl, get_proc_address, NULL, vo->log); return 0; fail: angle_uninit(ctx); return -1; }
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 int drm_egl_init(struct MPGLContext *ctx, int flags) { if (ctx->vo->probing) { MP_VERBOSE(ctx->vo, "DRM EGL backend can be activated only manually.\n"); return -1; } struct priv *p = ctx->priv; p->kms = NULL; p->old_crtc = NULL; p->gbm.surface = NULL; p->gbm.device = NULL; p->active = false; p->waiting_for_flip = false; p->ev.version = DRM_EVENT_CONTEXT_VERSION; p->ev.page_flip_handler = page_flipped; p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, ctx->vo->log); if (p->vt_switcher_active) { vt_switcher_acquire(&p->vt_switcher, acquire_vt, ctx); vt_switcher_release(&p->vt_switcher, release_vt, ctx); } else { MP_WARN(ctx->vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n"); } MP_VERBOSE(ctx->vo, "Initializing KMS\n"); p->kms = kms_create(ctx->vo->log, ctx->vo->opts->drm_connector_spec, ctx->vo->opts->drm_mode_id); if (!p->kms) { MP_ERR(ctx->vo, "Failed to create KMS.\n"); return -1; } if (!init_gbm(ctx)) { MP_ERR(ctx->vo, "Failed to setup GBM.\n"); return -1; } if (!init_egl(ctx, flags)) { MP_ERR(ctx->vo, "Failed to setup EGL.\n"); return -1; } if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface, p->egl.context)) { MP_ERR(ctx->vo, "Failed to make context current.\n"); return -1; } const char *egl_exts = eglQueryString(p->egl.display, EGL_EXTENSIONS); void *(*gpa)(const GLubyte*) = (void *(*)(const GLubyte*))eglGetProcAddress; mpgl_load_functions(ctx->gl, gpa, egl_exts, ctx->vo->log); ctx->native_display_type = "drm"; ctx->native_display = (void *)(intptr_t)p->kms->fd; // required by gbm_surface_lock_front_buffer eglSwapBuffers(p->egl.display, p->egl.surface); MP_VERBOSE(ctx->vo, "Preparing framebuffer\n"); p->gbm.bo = gbm_surface_lock_front_buffer(p->gbm.surface); if (!p->gbm.bo) { MP_ERR(ctx->vo, "Failed to lock GBM surface.\n"); return -1; } update_framebuffer_from_bo(ctx, p->gbm.bo); if (!p->fb.id) { MP_ERR(ctx->vo, "Failed to create framebuffer.\n"); return -1; } if (!crtc_setup(ctx)) { MP_ERR(ctx->vo, "Failed to set CRTC for connector %u: %s\n", p->kms->connector->connector_id, mp_strerror(errno)); return -1; } return 0; }