Пример #1
0
static void destroy_gl(void *ptr)
{
    struct MPGLContext *ctx = ptr;
    struct w32_context *w32_ctx = ctx->priv;
    if (w32_ctx->context)
        wglDeleteContext(w32_ctx->context);
    w32_ctx->context = 0;
    if (w32_ctx->hdc)
        ReleaseDC(vo_w32_hwnd(ctx->vo), w32_ctx->hdc);
    w32_ctx->hdc = NULL;
}
Пример #2
0
static bool create_dc(struct MPGLContext *ctx, int flags)
{
    struct w32_context *w32_ctx = ctx->priv;
    HWND win = vo_w32_hwnd(ctx->vo);

    if (w32_ctx->hdc)
        return true;

    HDC hdc = GetDC(win);
    if (!hdc)
        return false;

    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof pfd);
    pfd.nSize = sizeof pfd;
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;
    int pf = ChoosePixelFormat(hdc, &pfd);

    if (!pf) {
        MP_ERR(ctx->vo, "unable to select a valid pixel format!\n");
        ReleaseDC(win, hdc);
        return false;
    }

    SetPixelFormat(hdc, pf, &pfd);

    int pfmt = GetPixelFormat(hdc);
    if (DescribePixelFormat(hdc, pfmt, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) {
        ctx->depth_r = pfd.cRedBits;
        ctx->depth_g = pfd.cGreenBits;
        ctx->depth_b = pfd.cBlueBits;
    }

    w32_ctx->hdc = hdc;
    return true;
}
Пример #3
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;
}
Пример #4
0
static void d3d_init(struct MPGLContext *ctx)
{
    HRESULT hr;
    struct priv *p = ctx->priv;
    struct vo *vo = ctx->vo;
    IDXGIDevice *dxgi_dev = NULL;
    IDXGIAdapter *dxgi_adapter = NULL;
    IDXGIAdapter1 *dxgi_adapter1 = NULL;
    IDXGIFactory *dxgi_factory = NULL;

    PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT =
        (PFNEGLQUERYDISPLAYATTRIBEXTPROC)eglGetProcAddress("eglQueryDisplayAttribEXT");
    PFNEGLQUERYDEVICEATTRIBEXTPROC eglQueryDeviceAttribEXT =
        (PFNEGLQUERYDEVICEATTRIBEXTPROC)eglGetProcAddress("eglQueryDeviceAttribEXT");
    if (!eglQueryDisplayAttribEXT || !eglQueryDeviceAttribEXT) {
        MP_VERBOSE(vo, "Missing EGL_EXT_device_query\n");
        goto done;
    }

    EGLAttrib dev_attr;
    if (!eglQueryDisplayAttribEXT(p->egl_display, EGL_DEVICE_EXT, &dev_attr)) {
        MP_VERBOSE(vo, "Missing EGL_EXT_device_query\n");
        goto done;
    }

    // If ANGLE is in D3D11 mode, get the underlying ID3D11Device
    EGLDeviceEXT dev = (EGLDeviceEXT)dev_attr;
    EGLAttrib d3d11_dev_attr;
    if (eglQueryDeviceAttribEXT(dev, EGL_D3D11_DEVICE_ANGLE, &d3d11_dev_attr)) {
        ID3D11Device *d3d11_dev = (ID3D11Device*)d3d11_dev_attr;

        hr = ID3D11Device_QueryInterface(d3d11_dev, &IID_IDXGIDevice,
            (void**)&dxgi_dev);
        if (FAILED(hr)) {
            MP_ERR(vo, "Device is not a IDXGIDevice\n");
            goto done;
        }

        hr = IDXGIDevice_GetAdapter(dxgi_dev, &dxgi_adapter);
        if (FAILED(hr)) {
            MP_ERR(vo, "Couldn't get IDXGIAdapter\n");
            goto done;
        }

        // Windows 8 can choose a software adapter even if mpv didn't ask for
        // one. If this is the case, show a warning message.
        hr = IDXGIAdapter_QueryInterface(dxgi_adapter, &IID_IDXGIAdapter1,
            (void**)&dxgi_adapter1);
        if (SUCCEEDED(hr)) {
            DXGI_ADAPTER_DESC1 desc;
            hr = IDXGIAdapter1_GetDesc1(dxgi_adapter1, &desc);
            if (SUCCEEDED(hr)) {
                if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
                    show_sw_adapter_msg(ctx);

                // If the primary display adapter is a software adapter, the
                // DXGI_ADAPTER_FLAG_SOFTWARE won't be set, but the device IDs
                // should still match the Microsoft Basic Render Driver
                if (desc.VendorId == 0x1414 && desc.DeviceId == 0x8c)
                    show_sw_adapter_msg(ctx);
            }
        }

        hr = IDXGIAdapter_GetParent(dxgi_adapter, &IID_IDXGIFactory,
            (void**)&dxgi_factory);
        if (FAILED(hr)) {
            MP_ERR(vo, "Couldn't get IDXGIFactory\n");
            goto done;
        }

        // Prevent DXGI from making changes to the VO window, otherwise in
        // non-DirectComposition mode it will hook the Alt+Enter keystroke and
        // make it trigger an ugly transition to exclusive fullscreen mode
        // instead of running the user-set command.
        IDXGIFactory_MakeWindowAssociation(dxgi_factory, vo_w32_hwnd(vo),
            DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER |
            DXGI_MWA_NO_PRINT_SCREEN);
    }

done:
    if (dxgi_dev)
        IDXGIDevice_Release(dxgi_dev);
    if (dxgi_adapter)
        IDXGIAdapter_Release(dxgi_adapter);
    if (dxgi_adapter1)
        IDXGIAdapter1_Release(dxgi_adapter1);
    if (dxgi_factory)
        IDXGIFactory_Release(dxgi_factory);
}
Пример #5
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;
}