diff options
-rw-r--r-- | DOCS/man/options.rst | 1 | ||||
-rw-r--r-- | options/options.c | 1 | ||||
-rw-r--r-- | video/d3d.h | 2 | ||||
-rw-r--r-- | video/d3d11va.c | 13 | ||||
-rw-r--r-- | video/d3d11va.h | 1 | ||||
-rw-r--r-- | video/decode/d3d11va.c | 33 | ||||
-rw-r--r-- | video/decode/dxva2.c | 3 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 2 | ||||
-rw-r--r-- | video/hwdec.h | 1 | ||||
-rw-r--r-- | video/out/opengl/hwdec.c | 2 | ||||
-rw-r--r-- | video/out/opengl/hwdec_d3d11egl.c | 413 | ||||
-rw-r--r-- | wscript_build.py | 1 |
12 files changed, 471 insertions, 2 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index c96c10efbb..f7f92caabf 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -588,6 +588,7 @@ Video :dxva2: requires ``--vo=opengl:backend=angle`` or ``--vo=opengl:backend=dxinterop`` (Windows only) :dxva2-copy: copies video back to system RAM (Windows only) + :d3d11va: experimental, requires ``--vo=opengl:backend=angle`` (Windows only) :d3d11va-copy: experimental (Windows only) :rpi: requires ``--vo=rpi`` (Raspberry Pi only - default if available) diff --git a/options/options.c b/options/options.c index 1ae48a6fc2..90a72ee7c3 100644 --- a/options/options.c +++ b/options/options.c @@ -88,6 +88,7 @@ const struct m_opt_choice_alternatives mp_hwdec_names[] = { {"vaapi-copy", HWDEC_VAAPI_COPY}, {"dxva2", HWDEC_DXVA2}, {"dxva2-copy", HWDEC_DXVA2_COPY}, + {"d3d11va", HWDEC_D3D11VA}, {"d3d11va-copy",HWDEC_D3D11VA_COPY}, {"rpi", HWDEC_RPI}, {"mediacodec", HWDEC_MEDIACODEC}, diff --git a/video/d3d.h b/video/d3d.h index 30bee49adc..b5cf365f7f 100644 --- a/video/d3d.h +++ b/video/d3d.h @@ -2,12 +2,14 @@ #define MP_D3D_H_ #include <d3d9.h> +#include <d3d11.h> #include "hwdec.h" struct mp_d3d_ctx { struct mp_hwdec_ctx hwctx; IDirect3DDevice9 *d3d9_device; + ID3D11Device *d3d11_device; }; #endif diff --git a/video/d3d11va.c b/video/d3d11va.c index e27d7952cd..e64c26191c 100644 --- a/video/d3d11va.c +++ b/video/d3d11va.c @@ -21,6 +21,7 @@ struct d3d11va_surface { HMODULE d3d11_dll; ID3D11Texture2D *texture; + int subindex; ID3D11VideoDecoderOutputView *surface; }; @@ -38,6 +39,14 @@ ID3D11Texture2D *d3d11_texture_in_mp_image(struct mp_image *mpi) return surface->texture; } +int d3d11_subindex_in_mp_image(struct mp_image *mpi) +{ + if (!mpi || mpi->imgfmt != IMGFMT_D3D11VA) + return -1; + struct d3d11va_surface *surface = (void *)mpi->planes[0]; + return surface->subindex; +} + static void d3d11va_release_img(void *arg) { struct d3d11va_surface *surface = arg; @@ -69,6 +78,10 @@ struct mp_image *d3d11va_new_ref(ID3D11VideoDecoderOutputView *view, ID3D11VideoDecoderOutputView_GetResource( surface->surface, (ID3D11Resource **)&surface->texture); + D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC surface_desc; + ID3D11VideoDecoderOutputView_GetDesc(surface->surface, &surface_desc); + surface->subindex = surface_desc.Texture2D.ArraySlice; + struct mp_image *mpi = mp_image_new_custom_ref(NULL, surface, d3d11va_release_img); if (!mpi) diff --git a/video/d3d11va.h b/video/d3d11va.h index db2f295241..bbe2c4639f 100644 --- a/video/d3d11va.h +++ b/video/d3d11va.h @@ -24,6 +24,7 @@ struct mp_image; ID3D11VideoDecoderOutputView *d3d11_surface_in_mp_image(struct mp_image *mpi); ID3D11Texture2D *d3d11_texture_in_mp_image(struct mp_image *mpi); +int d3d11_subindex_in_mp_image(struct mp_image *mpi); struct mp_image *d3d11va_new_ref(ID3D11VideoDecoderOutputView *view, int w, int h); diff --git a/video/decode/d3d11va.c b/video/decode/d3d11va.c index c73ce2cab6..b94869d29b 100644 --- a/video/decode/d3d11va.c +++ b/video/decode/d3d11va.c @@ -26,6 +26,7 @@ #include "video/hwdec.h" #include "video/d3d11va.h" +#include "video/d3d.h" #include "d3d.h" #define ADDITIONAL_SURFACES (4 + HWDEC_DELAY_QUEUE_COUNT) @@ -449,8 +450,22 @@ static int d3d11va_init(struct lavc_ctx *s) p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); } - if (!create_device(s, FALSE)) + if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx) + p->device = s->hwdec_info->hwctx->d3d_ctx->d3d11_device; + + if (p->device) { + ID3D11Device_AddRef(p->device); + ID3D11Device_GetImmediateContext(p->device, &p->device_ctx); + if (!p->device_ctx) + goto fail; + MP_VERBOSE(p, "Using VO-supplied device %p.\n", p->device); + } else if (s->hwdec->type == HWDEC_D3D11VA) { + MP_ERR(p, "No Direct3D device provided for native d3d11 decoding\n"); goto fail; + } else { + if (!create_device(s, FALSE)) + goto fail; + } hr = ID3D11DeviceContext_QueryInterface(p->device_ctx, &IID_ID3D11VideoContext, @@ -487,9 +502,25 @@ static int d3d11va_probe(struct vd_lavc_hwdec *hwdec, const char *codec) { hwdec_request_api(info, "d3d11va"); + // d3d11va-copy can do without external context; dxva2 requires it. + if (hwdec->type != HWDEC_D3D11VA_COPY) { + if (!info || !info->hwctx || !info->hwctx->d3d_ctx || + !info->hwctx->d3d_ctx->d3d11_device) + return HWDEC_ERR_NO_CTX; + } return d3d_probe_codec(codec); } +const struct vd_lavc_hwdec mp_vd_lavc_d3d11va = { + .type = HWDEC_D3D11VA, + .image_format = IMGFMT_D3D11VA, + .probe = d3d11va_probe, + .init = d3d11va_init, + .uninit = d3d11va_uninit, + .init_decoder = d3d11va_init_decoder, + .allocate_image = d3d11va_allocate_image, +}; + const struct vd_lavc_hwdec mp_vd_lavc_d3d11va_copy = { .type = HWDEC_D3D11VA_COPY, .image_format = IMGFMT_D3D11VA, diff --git a/video/decode/dxva2.c b/video/decode/dxva2.c index 2c98c3abcc..e6499f96f2 100644 --- a/video/decode/dxva2.c +++ b/video/decode/dxva2.c @@ -494,7 +494,8 @@ static int dxva2_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, // dxva2-copy can do without external context; dxva2 requires it. if (hwdec->type != HWDEC_DXVA2_COPY) { if (!info || !info->hwctx || !info->hwctx->d3d_ctx || - info->hwctx->type == HWDEC_DXVA2_COPY) + info->hwctx->type == HWDEC_DXVA2_COPY || + !info->hwctx->d3d_ctx->d3d9_device) return HWDEC_ERR_NO_CTX; } return d3d_probe_codec(codec); diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 45aaa22599..810753cf74 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -126,6 +126,7 @@ extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi; extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy; extern const struct vd_lavc_hwdec mp_vd_lavc_dxva2; extern const struct vd_lavc_hwdec mp_vd_lavc_dxva2_copy; +extern const struct vd_lavc_hwdec mp_vd_lavc_d3d11va; extern const struct vd_lavc_hwdec mp_vd_lavc_d3d11va_copy; static const struct vd_lavc_hwdec mp_vd_lavc_rpi = { @@ -158,6 +159,7 @@ static const struct vd_lavc_hwdec *const hwdec_list[] = { &mp_vd_lavc_dxva2_copy, #endif #if HAVE_D3D11VA_HWACCEL + &mp_vd_lavc_d3d11va, &mp_vd_lavc_d3d11va_copy, #endif #if HAVE_ANDROID diff --git a/video/hwdec.h b/video/hwdec.h index 4deba76211..377f6779d1 100644 --- a/video/hwdec.h +++ b/video/hwdec.h @@ -15,6 +15,7 @@ enum hwdec_type { HWDEC_VAAPI_COPY, HWDEC_DXVA2, HWDEC_DXVA2_COPY, + HWDEC_D3D11VA, HWDEC_D3D11VA_COPY, HWDEC_RPI, HWDEC_MEDIACODEC, diff --git a/video/out/opengl/hwdec.c b/video/out/opengl/hwdec.c index b58af9bae9..02aa0c2cd2 100644 --- a/video/out/opengl/hwdec.c +++ b/video/out/opengl/hwdec.c @@ -29,6 +29,7 @@ extern const struct gl_hwdec_driver gl_hwdec_vaglx; extern const struct gl_hwdec_driver gl_hwdec_videotoolbox; extern const struct gl_hwdec_driver gl_hwdec_vdpau; extern const struct gl_hwdec_driver gl_hwdec_dxva2egl; +extern const struct gl_hwdec_driver gl_hwdec_d3d11egl; extern const struct gl_hwdec_driver gl_hwdec_dxva2gldx; extern const struct gl_hwdec_driver gl_hwdec_dxva2; @@ -47,6 +48,7 @@ static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = { #endif #if HAVE_DXVA2_HWACCEL #if HAVE_EGL_ANGLE + &gl_hwdec_d3d11egl, &gl_hwdec_dxva2egl, #endif #if HAVE_GL_DXINTEROP diff --git a/video/out/opengl/hwdec_d3d11egl.c b/video/out/opengl/hwdec_d3d11egl.c new file mode 100644 index 0000000000..44bab2c245 --- /dev/null +++ b/video/out/opengl/hwdec_d3d11egl.c @@ -0,0 +1,413 @@ +/* + * 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 <assert.h> +#include <windows.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include "common/common.h" +#include "osdep/timer.h" +#include "osdep/windows_utils.h" +#include "hwdec.h" +#include "video/d3d11va.h" +#include "video/d3d.h" +#include "video/hwdec.h" + +struct priv { + struct mp_d3d_ctx ctx; + + ID3D11Device *d3d11_device; + ID3D11VideoDevice *video_dev; + ID3D11VideoContext *video_ctx; + + EGLDisplay egl_display; + EGLConfig egl_config; + EGLSurface egl_surface; + + ID3D11Texture2D *texture; + ID3D11VideoProcessor *video_proc; + ID3D11VideoProcessorEnumerator *vp_enum; + ID3D11VideoProcessorOutputView *out_view; + int c_w, c_h; + + GLuint gl_texture; +}; + +static void destroy_video_proc(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + + if (p->out_view) + ID3D11VideoProcessorOutputView_Release(p->out_view); + p->out_view = NULL; + + if (p->video_proc) + ID3D11VideoProcessor_Release(p->video_proc); + p->video_proc = NULL; + + if (p->vp_enum) + ID3D11VideoProcessorEnumerator_Release(p->vp_enum); + p->vp_enum = NULL; +} + +static void destroy_objects(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + GL *gl = hw->gl; + + gl->DeleteTextures(1, &p->gl_texture); + p->gl_texture = 0; + + if (p->egl_display && p->egl_surface) { + eglReleaseTexImage(p->egl_display, p->egl_surface, EGL_BACK_BUFFER); + eglDestroySurface(p->egl_display, p->egl_surface); + } + p->egl_surface = NULL; + + if (p->texture) + ID3D11Texture2D_Release(p->texture); + p->texture = NULL; + + destroy_video_proc(hw); +} + +static void destroy(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + + destroy_objects(hw); + + if (p->video_ctx) + ID3D11VideoContext_Release(p->video_ctx); + p->video_ctx = NULL; + + if (p->video_dev) + ID3D11VideoDevice_Release(p->video_dev); + p->video_dev = NULL; + + if (p->d3d11_device) + ID3D11Device_Release(p->d3d11_device); + p->d3d11_device = NULL; +} + +static int create(struct gl_hwdec *hw) +{ + if (hw->hwctx) + return -1; + + EGLDisplay egl_display = eglGetCurrentDisplay(); + if (!egl_display) + return -1; + + const char *exts = eglQueryString(egl_display, EGL_EXTENSIONS); + if (!exts || !strstr(exts, "EGL_ANGLE_d3d_share_handle_client_buffer") || + !strstr(exts, "EGL_EXT_device_query")) + return -1; + + PFNEGLQUERYDISPLAYATTRIBEXTPROC p_eglQueryDisplayAttribEXT = + (void *)eglGetProcAddress("eglQueryDisplayAttribEXT"); + PFNEGLQUERYDEVICEATTRIBEXTPROC p_eglQueryDeviceAttribEXT = + (void *)eglGetProcAddress("eglQueryDeviceAttribEXT"); + if (!p_eglQueryDisplayAttribEXT || !p_eglQueryDeviceAttribEXT) + return -1; + + HRESULT hr; + struct priv *p = talloc_zero(hw, struct priv); + hw->priv = p; + + p->egl_display = egl_display; + + EGLAttrib device = 0; + if (!p_eglQueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &device)) + goto fail; + EGLAttrib d3d_device = 0; + if (!p_eglQueryDeviceAttribEXT((EGLDeviceEXT)device, EGL_D3D11_DEVICE_ANGLE, + &d3d_device)) + { + MP_ERR(hw, "Could not get EGL_D3D11_DEVICE_ANGLE from ANGLE.\n"); + goto fail; + } + + p->d3d11_device = (ID3D11Device *)d3d_device; + if (!p->d3d11_device) + goto fail; + ID3D11Device_AddRef(p->d3d11_device); + + ID3D10Multithread *multithread; + hr = ID3D11Device_QueryInterface(p->d3d11_device, &IID_ID3D10Multithread, + (void **)&multithread); + if (FAILED(hr)) { + ID3D10Multithread_Release(multithread); + MP_ERR(hw, "Failed to get Multithread interface: %s\n", + mp_HRESULT_to_str(hr)); + goto fail; + } + ID3D10Multithread_SetMultithreadProtected(multithread, TRUE); + ID3D10Multithread_Release(multithread); + + hr = ID3D11Device_QueryInterface(p->d3d11_device, &IID_ID3D11VideoDevice, + (void **)&p->video_dev); + if (FAILED(hr)) + goto fail; + + ID3D11DeviceContext *device_ctx; + ID3D11Device_GetImmediateContext(p->d3d11_device, &device_ctx); + if (!device_ctx) + goto fail; + hr = ID3D11DeviceContext_QueryInterface(device_ctx, &IID_ID3D11VideoContext, + (void **)&p->video_ctx); + ID3D11DeviceContext_Release(device_ctx); + if (FAILED(hr)) + goto fail; + + EGLint attrs[] = { + EGL_BUFFER_SIZE, 32, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_ALPHA_SIZE, 8, + EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE, + EGL_NONE + }; + EGLint count; + if (!eglChooseConfig(p->egl_display, attrs, &p->egl_config, 1, &count) || + !count) { + MP_ERR(hw, "Failed to get EGL surface configuration\n"); + goto fail; + } + + hw->converted_imgfmt = IMGFMT_RGB0; + + p->ctx.d3d11_device = p->d3d11_device; + p->ctx.hwctx.type = HWDEC_D3D11VA; + p->ctx.hwctx.d3d_ctx = &p->ctx; + + hw->hwctx = &p->ctx.hwctx; + return 0; +fail: + destroy(hw); + return -1; +} + +static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) +{ + struct priv *p = hw->priv; + GL *gl = hw->gl; + HRESULT hr; + + destroy_objects(hw); + + assert(params->imgfmt == hw->driver->imgfmt); + + D3D11_TEXTURE2D_DESC texdesc = { + .Width = params->w, + .Height = params->h, + .Format = DXGI_FORMAT_B8G8R8A8_UNORM, + .MipLevels = 1, + .ArraySize = 1, + .SampleDesc = { .Count = 1 }, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + .MiscFlags = D3D11_RESOURCE_MISC_SHARED, + }; + hr = ID3D11Device_CreateTexture2D(p->d3d11_device, &texdesc, NULL, &p->texture); + if (FAILED(hr)) { + MP_ERR(hw, "Failed to create texture: %s\n", mp_HRESULT_to_str(hr)); + goto fail; + } + + HANDLE share_handle = NULL; + IDXGIResource *res; + + hr = IUnknown_QueryInterface(p->texture, &IID_IDXGIResource, (void **)&res); + if (FAILED(hr)) + goto fail; + + hr = IDXGIResource_GetSharedHandle(res, &share_handle); + if (FAILED(hr)) + share_handle = NULL; + + IDXGIResource_Release(res); + + if (!share_handle) + goto fail; + + EGLint attrib_list[] = { + EGL_WIDTH, params->w, + EGL_HEIGHT, params->h, + EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_NONE + }; + p->egl_surface = eglCreatePbufferFromClientBuffer( + p->egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, + share_handle, p->egl_config, attrib_list); + if (p->egl_surface == EGL_NO_SURFACE) { + MP_ERR(hw, "Failed to create EGL surface\n"); + goto fail; + } + + gl->GenTextures(1, &p->gl_texture); + gl->BindTexture(GL_TEXTURE_2D, p->gl_texture); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->BindTexture(GL_TEXTURE_2D, 0); + + return 0; +fail: + destroy_objects(hw); + return -1; +} + +static int create_video_proc(struct gl_hwdec *hw, struct mp_image_params *params) +{ + struct priv *p = hw->priv; + HRESULT hr; + + destroy_video_proc(hw); + + // Note: we skip any deinterlacing considerations for now. + D3D11_VIDEO_PROCESSOR_CONTENT_DESC vpdesc = { + .InputWidth = p->c_w, + .InputHeight = p->c_h, + .OutputWidth = params->w, + .OutputHeight = params->h, + }; + hr = ID3D11VideoDevice_CreateVideoProcessorEnumerator(p->video_dev, &vpdesc, + &p->vp_enum); + if (FAILED(hr)) + goto fail; + + // Assume RateConversionIndex==0 always works fine for us. + hr = ID3D11VideoDevice_CreateVideoProcessor(p->video_dev, p->vp_enum, 0, + &p->video_proc); + if (FAILED(hr)) { + MP_ERR(hw, "Failed to create D3D11 video processor.\n"); + goto fail; + } + + D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC outdesc = { + .ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D, + }; + hr = ID3D11VideoDevice_CreateVideoProcessorOutputView(p->video_dev, + (ID3D11Resource *)p->texture, + p->vp_enum, &outdesc, + &p->out_view); + if (FAILED(hr)) + goto fail; + + // Note: libavcodec does not support cropping left/top with hwaccel. + RECT src_rc = { + .right = params->w, + .bottom = params->h, + }; + ID3D11VideoContext_VideoProcessorSetStreamSourceRect(p->video_ctx, + p->video_proc, + 0, TRUE, &src_rc); + + // This is supposed to stop drivers from fucking up the video quality. + ID3D11VideoContext_VideoProcessorSetStreamAutoProcessingMode(p->video_ctx, + p->video_proc, + 0, FALSE); + + D3D11_VIDEO_PROCESSOR_COLOR_SPACE csp = { + .YCbCr_Matrix = params->colorspace != MP_CSP_BT_601, + }; + ID3D11VideoContext_VideoProcessorSetStreamColorSpace(p->video_ctx, + p->video_proc, + 0, &csp); + + return 0; +fail: + destroy_video_proc(hw); + return -1; +} + +static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image, + GLuint *out_textures) +{ + struct priv *p = hw->priv; + GL *gl = hw->gl; + HRESULT hr; + ID3D11VideoProcessorInputView *in_view = NULL; + + if (!p->gl_texture) + return -1; + + ID3D11Texture2D *d3d_tex = d3d11_texture_in_mp_image(hw_image); + int d3d_subindex = d3d11_subindex_in_mp_image(hw_image); + if (!d3d_tex) + return -1; + + D3D11_TEXTURE2D_DESC texdesc; + ID3D11Texture2D_GetDesc(d3d_tex, &texdesc); + if (!p->video_proc || p->c_w != texdesc.Width || p->c_h != texdesc.Height) { + p->c_w = texdesc.Width; + p->c_h = texdesc.Height; + if (create_video_proc(hw, &hw_image->params) < 0) + return -1; + } + + D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC indesc = { + .FourCC = 0, // huh? + .ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D, + .Texture2D = { + .ArraySlice = d3d_subindex, + }, + }; + hr = ID3D11VideoDevice_CreateVideoProcessorInputView(p->video_dev, + (ID3D11Resource *)d3d_tex, + p->vp_enum, &indesc, + &in_view); + if (FAILED(hr)) { + MP_ERR(hw, "Could not create ID3D11VideoProcessorInputView\n"); + return -1; + } + + D3D11_VIDEO_PROCESSOR_STREAM stream = { + .Enable = TRUE, + .pInputSurface = in_view, + }; + hr = ID3D11VideoContext_VideoProcessorBlt(p->video_ctx, p->video_proc, + p->out_view, 0, 1, &stream); + ID3D11VideoProcessorInputView_Release(in_view); + if (FAILED(hr)) { + MP_ERR(hw, "VideoProcessorBlt failed.\n"); + return -1; + } + + gl->BindTexture(GL_TEXTURE_2D, p->gl_texture); + eglBindTexImage(p->egl_display, p->egl_surface, EGL_BACK_BUFFER); + gl->BindTexture(GL_TEXTURE_2D, 0); + + out_textures[0] = p->gl_texture; + return 0; +} + +const struct gl_hwdec_driver gl_hwdec_d3d11egl = { + .name = "d3d11-egl", + .api = HWDEC_D3D11VA, + .imgfmt = IMGFMT_D3D11VA, + .create = create, + .reinit = reinit, + .map_image = map_image, + .destroy = destroy, +}; diff --git a/wscript_build.py b/wscript_build.py index 7dd28c31bb..3ee2b31d65 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -342,6 +342,7 @@ def build(ctx): ( "video/out/opengl/context_x11egl.c", "egl-x11" ), ( "video/out/opengl/egl_helpers.c", "egl-helpers" ), ( "video/out/opengl/hwdec.c", "gl" ), + ( "video/out/opengl/hwdec_d3d11egl.c", "egl-angle" ), ( "video/out/opengl/hwdec_dxva2.c", "gl-win32" ), ( "video/out/opengl/hwdec_dxva2gldx.c", "gl-dxinterop" ), ( "video/out/opengl/hwdec_dxva2egl.c", "egl-angle" ), |