Пример #1
1
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;
}
Пример #2
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;
}
Пример #3
0
Файл: x11.c Проект: madokama/mpv
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
Файл: gl_w32.c Проект: benf/mpv
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;
}
Пример #9
0
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;
}
Пример #10
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;

    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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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;
}
Пример #15
0
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;
}
Пример #16
0
Файл: gl_w32.c Проект: benf/mpv
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;
}
Пример #17
0
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;
}