1 /*****************************************************************************
2 * direct3d11.c: Windows Direct3D11 video output module
3 *****************************************************************************
4 * Copyright (C) 2014-2015 VLC authors and VideoLAN
6 * Authors: Martell Malone <martellmalone@gmail.com>
7 * Steve Lhomme <robux4@gmail.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
30 #include <vlc_vout_display.h>
36 /* avoided until we can pass ISwapchainPanel without c++/cx mode
37 # include <windows.ui.xaml.media.dxinterop.h> */
43 # define D3D11CreateDeviceAndSwapChain(args...) sys->OurD3D11CreateDeviceAndSwapChain(args)
45 # define D3D11CreateDevice(args...) sys->OurD3D11CreateDevice(args)
47 # define D3DCompile(args...) sys->OurD3DCompile(args)
50 DEFINE_GUID(GUID_SWAPCHAIN_WIDTH
, 0xf1b59347, 0x1643, 0x411a, 0xad, 0x6b, 0xc7, 0x80, 0x17, 0x7a, 0x06, 0xb6);
51 DEFINE_GUID(GUID_SWAPCHAIN_HEIGHT
, 0x6ea976a0, 0x9d60, 0x4bb7, 0xa5, 0xa9, 0x7d, 0xd1, 0x18, 0x7f, 0xc9, 0xbd);
53 static int Open(vlc_object_t
*);
54 static void Close(vlc_object_t
*);
56 #define D3D11_HELP N_("Recommended video output for Windows 8 and later versions")
57 #define HW_BLENDING_TEXT N_("Use hardware blending support")
58 #define HW_BLENDING_LONGTEXT N_(\
59 "Try to use hardware acceleration for subtitle/OSD blending.")
62 set_shortname("Direct3D11")
63 set_description(N_("Direct3D11 video output"))
65 set_category(CAT_VIDEO
)
66 set_subcategory(SUBCAT_VIDEO_VOUT
)
68 add_bool("direct3d11-hw-blending", true, HW_BLENDING_TEXT
, HW_BLENDING_LONGTEXT
, true)
71 add_integer("winrt-d3ddevice", 0x0, NULL
, NULL
, true); /* ID3D11Device* */
72 add_integer("winrt-d3dcontext", 0x0, NULL
, NULL
, true); /* ID3D11DeviceContext* */
73 add_integer("winrt-swapchain", 0x0, NULL
, NULL
, true); /* IDXGISwapChain1* */
76 set_capability("vout display", 240)
77 add_shortcut("direct3d11")
78 set_callbacks(Open
, Close
)
84 DXGI_FORMAT formatTexture
;
90 static const d3d_format_t d3d_formats
[] = {
91 { "I420", DXGI_FORMAT_NV12
, VLC_CODEC_I420
, DXGI_FORMAT_R8_UNORM
, DXGI_FORMAT_R8G8_UNORM
},
92 { "YV12", DXGI_FORMAT_NV12
, VLC_CODEC_YV12
, DXGI_FORMAT_R8_UNORM
, DXGI_FORMAT_R8G8_UNORM
},
93 { "NV12", DXGI_FORMAT_NV12
, VLC_CODEC_NV12
, DXGI_FORMAT_R8_UNORM
, DXGI_FORMAT_R8G8_UNORM
},
94 { "VA_NV12", DXGI_FORMAT_NV12
, VLC_CODEC_D3D11_OPAQUE
, DXGI_FORMAT_R8_UNORM
, DXGI_FORMAT_R8G8_UNORM
},
96 { "YUY2", DXGI_FORMAT_YUY2
, VLC_CODEC_I422
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0 },
97 { "AYUV", DXGI_FORMAT_AYUV
, VLC_CODEC_YUVA
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0 },
98 { "Y416", DXGI_FORMAT_Y416
, VLC_CODEC_I444_16L
, DXGI_FORMAT_R16G16B16A16_UINT
, 0 },
101 { "P010", DXGI_FORMAT_P010
, VLC_CODEC_I420_10L
, DXGI_FORMAT_R16_UNORM
, DXGI_FORMAT_R16_UNORM
},
102 { "Y210", DXGI_FORMAT_Y210
, VLC_CODEC_I422_10L
, DXGI_FORMAT_R16G16B16A16_UNORM
, 0 },
103 { "Y410", DXGI_FORMAT_Y410
, VLC_CODEC_I444_10L
, DXGI_FORMAT_R10G10B10A2_UNORM
, 0 },
104 { "NV11", DXGI_FORMAT_NV11
, VLC_CODEC_I411
, DXGI_FORMAT_R8_UNORM
, DXGI_FORMAT_R8G8_UNORM
},
106 { "R8G8B8A8", DXGI_FORMAT_R8G8B8A8_UNORM
, VLC_CODEC_RGBA
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0 },
107 { "B8G8R8A8", DXGI_FORMAT_B8G8R8A8_UNORM
, VLC_CODEC_BGRA
, DXGI_FORMAT_B8G8R8A8_UNORM
, 0 },
108 { "R8G8B8X8", DXGI_FORMAT_B8G8R8X8_UNORM
, VLC_CODEC_RGB32
, DXGI_FORMAT_B8G8R8X8_UNORM
, 0 },
109 { "B5G6R5", DXGI_FORMAT_B5G6R5_UNORM
, VLC_CODEC_RGB16
, DXGI_FORMAT_B5G6R5_UNORM
, 0 },
114 #ifdef HAVE_ID3D11VIDEODECODER
115 /* VLC_CODEC_D3D11_OPAQUE */
118 ID3D11VideoDecoderOutputView
*decoder
; /* may be NULL for pictures from the pool */
119 ID3D11Texture2D
*texture
;
120 ID3D11DeviceContext
*context
;
124 /* internal picture_t pool */
127 ID3D11Texture2D
*texture
;
129 } picture_sys_pool_t
;
131 /* matches the D3D11_INPUT_ELEMENT_DESC we setup */
132 typedef struct d3d_vertex_t
{
145 #define RECTWidth(r) (int)(r.right - r.left)
146 #define RECTHeight(r) (int)(r.bottom - r.top)
148 static int Open(vlc_object_t
*);
149 static void Close(vlc_object_t
*object
);
151 static picture_pool_t
*Pool(vout_display_t
*vd
, unsigned count
);
153 static void Prepare(vout_display_t
*, picture_t
*, subpicture_t
*subpicture
);
154 static void Display(vout_display_t
*, picture_t
*, subpicture_t
*subpicture
);
156 static HINSTANCE
Direct3D11LoadShaderLibrary(void);
157 static void Direct3D11Destroy(vout_display_t
*);
159 static int Direct3D11Open (vout_display_t
*, video_format_t
*);
160 static void Direct3D11Close(vout_display_t
*);
162 static int Direct3D11CreateResources (vout_display_t
*, video_format_t
*);
163 static void Direct3D11DestroyResources(vout_display_t
*);
165 static int Direct3D11CreatePool (vout_display_t
*, video_format_t
*);
166 static void Direct3D11DestroyPool(vout_display_t
*);
168 static void DestroyDisplayPicture(picture_t
*);
169 static void DestroyDisplayPoolPicture(picture_t
*);
170 static int Direct3D11MapTexture(picture_t
*);
171 static void Direct3D11DeleteRegions(int, picture_t
**);
172 static int Direct3D11MapSubpicture(vout_display_t
*, int *, picture_t
***, subpicture_t
*);
174 static int AllocQuad(vout_display_t
*, const video_format_t
*, d3d_quad_t
*,
175 d3d_quad_cfg_t
*, ID3D11PixelShader
*);
176 static void ReleaseQuad(d3d_quad_t
*);
177 static void UpdatePicQuadPosition(vout_display_t
*);
178 static void UpdateQuadPosition(vout_display_t
*, const d3d_quad_t
*, const RECT
*, int w
, int h
, float o
);
180 static void Manage(vout_display_t
*vd
);
182 /* All the #if USE_DXGI contain an alternative method to setup dx11
183 They both need to be benchmarked to see which performs better */
185 /* I have no idea why MS decided dxgi headers do not define this
186 As they do have prototypes for d3d11 functions */
187 typedef HRESULT(WINAPI
*PFN_CREATE_DXGI_FACTORY
)(REFIID riid
, void **ppFactory
);
190 /* TODO: Move to a direct3d11_shaders header */
191 static const char* globVertexShaderDefault
= "\
194 float4 Position : POSITION;\
195 float2 Texture : TEXCOORD0;\
196 float Opacity : OPACITY;\
201 float4 Position : SV_POSITION;\
202 float2 Texture : TEXCOORD0;\
203 float Opacity : OPACITY;\
206 VS_OUTPUT VS( VS_INPUT In )\
209 Output.Position = float4(In.Position.xy, 0.0f, 1.0f);\
210 Output.Texture = In.Texture;\
211 Output.Opacity = In.Opacity;\
216 static const char* globPixelShaderDefault
= "\
217 Texture2D shaderTexture;\
218 SamplerState SampleType;\
222 float4 Position : SV_POSITION;\
223 float2 Texture : TEXCOORD0;\
224 float Opacity : OPACITY;\
227 float4 PS( PS_INPUT In ) : SV_TARGET\
231 rgba = shaderTexture.Sample(SampleType, In.Texture);\
232 rgba.a = rgba.a * In.Opacity;\
237 static const char *globPixelShaderBiplanarI420_BT601_2RGB
= "\
238 Texture2D shaderTextureY;\
239 Texture2D shaderTextureUV;\
240 SamplerState SampleType;\
244 float4 Position : SV_POSITION;\
245 float2 Texture : TEXCOORD0;\
246 float Opacity : OPACITY;\
249 float4 PS( PS_INPUT In ) : SV_TARGET\
258 Y = shaderTextureY.Sample(SampleType, In.Texture).x;\
260 VCrPos = In.Texture / 2;\
261 VCr = shaderTextureUV.Sample(SampleType, VCrPos).x;\
263 UCbPos = In.Texture / 2;\
264 UCbPos.y = UCbPos.y + 0.5;\
265 UCb = shaderTextureUV.Sample(SampleType, UCbPos).x;\
267 Y = 1.164383561643836 * (Y - 0.0625);\
271 rgba.x = saturate(Y + 1.596026785714286 * VCr);\
272 rgba.y = saturate(Y - 0.812967647237771 * VCr - 0.391762290094914 * UCb);\
273 rgba.z = saturate(Y + 2.017232142857142 * UCb);\
274 rgba.a = In.Opacity;\
279 static const char *globPixelShaderBiplanarI420_BT709_2RGB
= "\
280 Texture2D shaderTextureY;\
281 Texture2D shaderTextureUV;\
282 SamplerState SampleType;\
286 float4 Position : SV_POSITION;\
287 float2 Texture : TEXCOORD0;\
288 float Opacity : OPACITY;\
291 float4 PS( PS_INPUT In ) : SV_TARGET\
300 Y = shaderTextureY.Sample(SampleType, In.Texture).x;\
302 VCrPos = In.Texture / 2;\
303 VCr = shaderTextureUV.Sample(SampleType, VCrPos).x;\
305 UCbPos = In.Texture / 2;\
306 UCbPos.y = UCbPos.y + 0.5;\
307 UCb = shaderTextureUV.Sample(SampleType, UCbPos).x;\
309 Y = 1.164383561643836 * (Y - 0.0625);\
313 rgba.x = saturate(Y + 1.792741071428571 * VCr);\
314 rgba.y = saturate(Y - 0.532909328559444 * VCr - 0.21324861427373 * UCb);\
315 rgba.z = saturate(Y + 2.112401785714286 * UCb);\
316 rgba.a = In.Opacity;\
321 static const char *globPixelShaderBiplanarYUV_BT601_2RGB
= "\
322 Texture2D shaderTextureY;\
323 Texture2D shaderTextureUV;\
324 SamplerState SampleType;\
328 float4 Position : SV_POSITION;\
329 float2 Texture : TEXCOORD0;\
330 float Opacity : OPACITY;\
333 float4 PS( PS_INPUT In ) : SV_TARGET\
337 yuv.x = shaderTextureY.Sample(SampleType, In.Texture).x;\
338 yuv.yz = shaderTextureUV.Sample(SampleType, In.Texture).xy;\
339 yuv.x = 1.164383561643836 * (yuv.x-0.0625);\
340 yuv.y = yuv.y - 0.5;\
341 yuv.z = yuv.z - 0.5;\
342 rgba.x = saturate(yuv.x + 1.596026785714286 * yuv.z);\
343 rgba.y = saturate(yuv.x - 0.812967647237771 * yuv.z - 0.391762290094914 * yuv.y);\
344 rgba.z = saturate(yuv.x + 2.017232142857142 * yuv.y);\
345 rgba.a = In.Opacity;\
350 static const char *globPixelShaderBiplanarYUV_BT709_2RGB
= "\
351 Texture2D shaderTextureY;\
352 Texture2D shaderTextureUV;\
353 SamplerState SampleType;\
357 float4 Position : SV_POSITION;\
358 float2 Texture : TEXCOORD0;\
359 float Opacity : OPACITY;\
362 float4 PS( PS_INPUT In ) : SV_TARGET\
366 yuv.x = shaderTextureY.Sample(SampleType, In.Texture).x;\
367 yuv.yz = shaderTextureUV.Sample(SampleType, In.Texture).xy;\
368 yuv.x = 1.164383561643836 * (yuv.x-0.0625);\
369 yuv.y = yuv.y - 0.5;\
370 yuv.z = yuv.z - 0.5;\
371 rgba.x = saturate(yuv.x + 1.792741071428571 * yuv.z);\
372 rgba.y = saturate(yuv.x - 0.532909328559444 * yuv.z - 0.21324861427373 * yuv.y);\
373 rgba.z = saturate(yuv.x + 2.112401785714286 * yuv.y);\
374 rgba.a = In.Opacity;\
379 static int Open(vlc_object_t
*object
)
381 vout_display_t
*vd
= (vout_display_t
*)object
;
383 #if !VLC_WINSTORE_APP
384 HINSTANCE hd3d11_dll
= LoadLibrary(TEXT("D3D11.DLL"));
386 msg_Warn(vd
, "cannot load d3d11.dll, aborting");
390 HINSTANCE hd3dcompiler_dll
= Direct3D11LoadShaderLibrary();
391 if (!hd3dcompiler_dll
) {
392 msg_Err(vd
, "cannot load d3dcompiler.dll, aborting");
393 FreeLibrary(hd3d11_dll
);
398 HINSTANCE hdxgi_dll
= LoadLibrary(TEXT("DXGI.DLL"));
400 msg_Warn(vd
, "cannot load dxgi.dll, aborting");
406 IDXGISwapChain1
* dxgiswapChain
= var_InheritInteger(vd
, "winrt-swapchain");
409 ID3D11Device
* d3ddevice
= var_InheritInteger(vd
, "winrt-d3ddevice");
412 ID3D11DeviceContext
* d3dcontext
= var_InheritInteger(vd
, "winrt-d3dcontext");
417 vout_display_sys_t
*sys
= vd
->sys
= calloc(1, sizeof(vout_display_sys_t
));
421 #if !VLC_WINSTORE_APP
422 sys
->hd3d11_dll
= hd3d11_dll
;
423 sys
->hd3dcompiler_dll
= hd3dcompiler_dll
;
425 sys
->OurD3DCompile
= (void *)GetProcAddress(sys
->hd3dcompiler_dll
, "D3DCompile");
426 if (!sys
->OurD3DCompile
) {
427 msg_Err(vd
, "Cannot locate reference to D3DCompile in d3dcompiler DLL");
428 Direct3D11Destroy(vd
);
433 sys
->hdxgi_dll
= hdxgi_dll
;
435 /* TODO : enable all dxgi versions from 1.3 -> 1.1 */
436 PFN_CREATE_DXGI_FACTORY OurCreateDXGIFactory
=
437 (void *)GetProcAddress(sys
->hdxgi_dll
, "CreateDXGIFactory");
438 if (!OurCreateDXGIFactory
) {
439 msg_Err(vd
, "Cannot locate reference to CreateDXGIFactory in dxgi DLL");
440 Direct3D11Destroy(vd
);
444 /* TODO : detect the directx version supported and use IID_IDXGIFactory3 or 2 */
445 HRESULT hr
= OurCreateDXGIFactory(&IID_IDXGIFactory
, (void **)&sys
->dxgifactory
);
447 msg_Err(vd
, "Could not create dxgi factory. (hr=0x%lX)", hr
);
448 Direct3D11Destroy(vd
);
452 sys
->OurD3D11CreateDeviceAndSwapChain
=
453 (void *)GetProcAddress(sys
->hd3d11_dll
, "D3D11CreateDeviceAndSwapChain");
454 if (!sys
->OurD3D11CreateDeviceAndSwapChain
) {
455 msg_Err(vd
, "Cannot locate reference to D3D11CreateDeviceAndSwapChain in d3d11 DLL");
456 Direct3D11Destroy(vd
);
461 sys
->OurD3D11CreateDevice
=
462 (void *)GetProcAddress(sys
->hd3d11_dll
, "D3D11CreateDevice");
463 if (!sys
->OurD3D11CreateDevice
) {
464 msg_Err(vd
, "Cannot locate reference to D3D11CreateDevice in d3d11 DLL");
465 Direct3D11Destroy(vd
);
471 sys
->dxgiswapChain
= dxgiswapChain
;
472 sys
->d3ddevice
= d3ddevice
;
473 sys
->d3dcontext
= d3dcontext
;
474 IDXGISwapChain_AddRef (sys
->dxgiswapChain
);
475 ID3D11Device_AddRef (sys
->d3ddevice
);
476 ID3D11DeviceContext_AddRef(sys
->d3dcontext
);
483 if (Direct3D11Open(vd
, &fmt
)) {
484 msg_Err(vd
, "Direct3D11 could not be opened");
488 vout_display_info_t info
= vd
->info
;
489 info
.is_slow
= fmt
.i_chroma
!= VLC_CODEC_D3D11_OPAQUE
;
490 info
.has_double_click
= true;
491 info
.has_hide_mouse
= false;
492 info
.has_pictures_invalid
= true;
493 info
.has_event_thread
= true;
494 info
.has_pictures_invalid
= fmt
.i_chroma
!= VLC_CODEC_D3D11_OPAQUE
;
496 if (var_InheritBool(vd
, "direct3d11-hw-blending") &&
497 sys
->d3dregion_format
!= DXGI_FORMAT_UNKNOWN
)
498 info
.subpicture_chromas
= sys
->pSubpictureChromas
;
500 info
.subpicture_chromas
= NULL
;
502 video_format_Clean(&vd
->fmt
);
503 video_format_Copy(&vd
->fmt
, &fmt
);
507 vd
->prepare
= Prepare
;
508 vd
->display
= Display
;
509 vd
->control
= CommonControl
;
512 msg_Dbg(vd
, "Direct3D11 Open Succeeded");
518 Direct3D11Destroy(vd
);
523 static void Close(vlc_object_t
*object
)
525 vout_display_t
* vd
= (vout_display_t
*)object
;
529 Direct3D11Destroy(vd
);
533 static picture_pool_t
*Pool(vout_display_t
*vd
, unsigned pool_size
)
535 if ( vd
->sys
->pool
!= NULL
)
536 return vd
->sys
->pool
;
538 #ifdef HAVE_ID3D11VIDEODECODER
539 picture_t
** pictures
= NULL
;
540 unsigned picture_count
= 0;
543 ID3D10Multithread
*pMultithread
;
544 hr
= ID3D11Device_QueryInterface( vd
->sys
->d3ddevice
, &IID_ID3D10Multithread
, (void **)&pMultithread
);
546 ID3D10Multithread_SetMultithreadProtected(pMultithread
, TRUE
);
547 ID3D10Multithread_Release(pMultithread
);
550 pictures
= calloc(pool_size
, sizeof(*pictures
));
554 D3D11_TEXTURE2D_DESC texDesc
;
555 ZeroMemory(&texDesc
, sizeof(texDesc
));
556 texDesc
.Width
= vd
->fmt
.i_width
;
557 texDesc
.Height
= vd
->fmt
.i_height
;
558 texDesc
.MipLevels
= 1;
559 texDesc
.Format
= vd
->sys
->picQuadConfig
.textureFormat
;
560 texDesc
.SampleDesc
.Count
= 1;
561 texDesc
.MiscFlags
= 0; //D3D11_RESOURCE_MISC_SHARED;
562 texDesc
.ArraySize
= 1;
563 texDesc
.Usage
= D3D11_USAGE_DYNAMIC
;
564 texDesc
.BindFlags
= D3D11_BIND_SHADER_RESOURCE
;
565 texDesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
;
567 unsigned surface_count
;
568 for (surface_count
= 0; surface_count
< pool_size
; surface_count
++) {
569 picture_sys_t
*picsys
= calloc(1, sizeof(*picsys
));
570 if (unlikely(picsys
== NULL
))
573 hr
= ID3D11Device_CreateTexture2D( vd
->sys
->d3ddevice
, &texDesc
, NULL
, &picsys
->texture
);
575 msg_Err(vd
, "CreateTexture2D %d failed. (hr=0x%0lx)", pool_size
, hr
);
579 picsys
->context
= vd
->sys
->d3dcontext
;
581 picture_resource_t resource
= {
583 .pf_destroy
= DestroyDisplayPoolPicture
,
586 picture_t
*picture
= picture_NewFromResource(&vd
->fmt
, &resource
);
587 if (unlikely(picture
== NULL
)) {
592 pictures
[surface_count
] = picture
;
593 /* each picture_t holds a ref to the context and release it on Destroy */
594 ID3D11DeviceContext_AddRef(picsys
->context
);
596 msg_Dbg(vd
, "ID3D11VideoDecoderOutputView succeed with %d surfaces (%dx%d)",
597 pool_size
, vd
->fmt
.i_width
, vd
->fmt
.i_height
);
599 picture_pool_configuration_t pool_cfg
;
600 memset(&pool_cfg
, 0, sizeof(pool_cfg
));
601 pool_cfg
.picture_count
= pool_size
;
602 pool_cfg
.picture
= pictures
;
604 vd
->sys
->pool
= picture_pool_NewExtended( &pool_cfg
);
607 if (vd
->sys
->pool
==NULL
&& pictures
) {
608 for (unsigned i
=0;i
<picture_count
; ++i
)
609 DestroyDisplayPoolPicture(pictures
[i
]);
613 return vd
->sys
->pool
;
616 #ifdef HAVE_ID3D11VIDEODECODER
617 static void DestroyDisplayPoolPicture(picture_t
*picture
)
619 picture_sys_t
*p_sys
= (picture_sys_t
*) picture
->p_sys
;
622 ID3D11Texture2D_Release(p_sys
->texture
);
629 static void DestroyDisplayPicture(picture_t
*picture
)
631 picture_sys_pool_t
*p_sys
= (picture_sys_pool_t
*) picture
->p_sys
;
634 ID3D11Texture2D_Release(p_sys
->texture
);
640 static HRESULT
UpdateBackBuffer(vout_display_t
*vd
)
642 vout_display_sys_t
*sys
= vd
->sys
;
644 ID3D11Texture2D
* pDepthStencil
;
645 ID3D11Texture2D
* pBackBuffer
;
646 uint32_t i_width
= RECTWidth(sys
->rect_dest_clipped
);
647 uint32_t i_height
= RECTHeight(sys
->rect_dest_clipped
);
649 UINT dataSize
= sizeof(i_width
);
650 hr
= IDXGISwapChain_GetPrivateData(sys
->dxgiswapChain
, &GUID_SWAPCHAIN_WIDTH
, &dataSize
, &i_width
);
652 msg_Err(vd
, "Can't get swapchain width, size %d. (hr=0x%lX)", hr
, dataSize
);
655 dataSize
= sizeof(i_height
);
656 hr
= IDXGISwapChain_GetPrivateData(sys
->dxgiswapChain
, &GUID_SWAPCHAIN_HEIGHT
, &dataSize
, &i_height
);
658 msg_Err(vd
, "Can't get swapchain height, size %d. (hr=0x%lX)", hr
, dataSize
);
663 if (sys
->d3drenderTargetView
) {
664 ID3D11RenderTargetView_Release(sys
->d3drenderTargetView
);
665 sys
->d3drenderTargetView
= NULL
;
667 if (sys
->d3ddepthStencilView
) {
668 ID3D11DepthStencilView_Release(sys
->d3ddepthStencilView
);
669 sys
->d3ddepthStencilView
= NULL
;
672 hr
= IDXGISwapChain_ResizeBuffers(sys
->dxgiswapChain
, 0, i_width
, i_height
,
673 DXGI_FORMAT_UNKNOWN
, 0);
675 msg_Err(vd
, "Failed to resize the backbuffer. (hr=0x%lX)", hr
);
679 hr
= IDXGISwapChain_GetBuffer(sys
->dxgiswapChain
, 0, &IID_ID3D11Texture2D
, (LPVOID
*)&pBackBuffer
);
681 msg_Err(vd
, "Could not get the backbuffer for the Swapchain. (hr=0x%lX)", hr
);
685 hr
= ID3D11Device_CreateRenderTargetView(sys
->d3ddevice
, (ID3D11Resource
*)pBackBuffer
, NULL
, &sys
->d3drenderTargetView
);
686 ID3D11Texture2D_Release(pBackBuffer
);
688 msg_Err(vd
, "Failed to create the target view. (hr=0x%lX)", hr
);
692 D3D11_TEXTURE2D_DESC deptTexDesc
;
693 memset(&deptTexDesc
, 0,sizeof(deptTexDesc
));
694 deptTexDesc
.ArraySize
= 1;
695 deptTexDesc
.BindFlags
= D3D11_BIND_DEPTH_STENCIL
;
696 deptTexDesc
.CPUAccessFlags
= 0;
697 deptTexDesc
.Format
= DXGI_FORMAT_D24_UNORM_S8_UINT
;
698 deptTexDesc
.Width
= i_width
;
699 deptTexDesc
.Height
= i_height
;
700 deptTexDesc
.MipLevels
= 1;
701 deptTexDesc
.MiscFlags
= 0;
702 deptTexDesc
.SampleDesc
.Count
= 1;
703 deptTexDesc
.SampleDesc
.Quality
= 0;
704 deptTexDesc
.Usage
= D3D11_USAGE_DEFAULT
;
706 hr
= ID3D11Device_CreateTexture2D(sys
->d3ddevice
, &deptTexDesc
, NULL
, &pDepthStencil
);
708 msg_Err(vd
, "Could not create the depth stencil texture. (hr=0x%lX)", hr
);
712 D3D11_DEPTH_STENCIL_VIEW_DESC depthViewDesc
;
713 memset(&depthViewDesc
, 0, sizeof(depthViewDesc
));
715 depthViewDesc
.Format
= deptTexDesc
.Format
;
716 depthViewDesc
.ViewDimension
= D3D11_DSV_DIMENSION_TEXTURE2D
;
717 depthViewDesc
.Texture2D
.MipSlice
= 0;
719 hr
= ID3D11Device_CreateDepthStencilView(sys
->d3ddevice
, (ID3D11Resource
*)pDepthStencil
, &depthViewDesc
, &sys
->d3ddepthStencilView
);
720 ID3D11Texture2D_Release(pDepthStencil
);
723 msg_Err(vd
, "Could not create the depth stencil view. (hr=0x%lX)", hr
);
728 vp
.Width
= (FLOAT
)i_width
;
729 vp
.Height
= (FLOAT
)i_height
;
735 ID3D11DeviceContext_RSSetViewports(sys
->d3dcontext
, 1, &vp
);
740 static void Manage(vout_display_t
*vd
)
742 vout_display_sys_t
*sys
= vd
->sys
;
743 RECT size_before
= sys
->rect_dest_clipped
;
747 if (RECTWidth(size_before
) != RECTWidth(sys
->rect_dest_clipped
) ||
748 RECTHeight(size_before
) != RECTHeight(sys
->rect_dest_clipped
))
750 msg_Dbg(vd
, "Manage detected size change %dx%d", RECTWidth(sys
->rect_dest_clipped
),
751 RECTHeight(sys
->rect_dest_clipped
));
753 UpdateBackBuffer(vd
);
755 UpdatePicQuadPosition(vd
);
759 static void Prepare(vout_display_t
*vd
, picture_t
*picture
, subpicture_t
*subpicture
)
761 vout_display_sys_t
*sys
= vd
->sys
;
763 #ifdef HAVE_ID3D11VIDEODECODER
764 if (picture
->format
.i_chroma
== VLC_CODEC_D3D11_OPAQUE
) {
767 box
.right
= picture
->format
.i_visible_width
;
769 box
.bottom
= picture
->format
.i_visible_height
;
773 picture_sys_t
*p_sys
= picture
->p_sys
;
774 ID3D11DeviceContext_CopySubresourceRegion(sys
->d3dcontext
,
775 (ID3D11Resource
*) sys
->picQuad
.pTexture
,
777 (ID3D11Resource
*) p_sys
->texture
,
783 int subpicture_region_count
= 0;
784 picture_t
**subpicture_regions
= NULL
;
785 Direct3D11MapSubpicture(vd
, &subpicture_region_count
, &subpicture_regions
, subpicture
);
786 Direct3D11DeleteRegions(sys
->d3dregion_count
, sys
->d3dregions
);
787 sys
->d3dregion_count
= subpicture_region_count
;
788 sys
->d3dregions
= subpicture_regions
;
792 static void DisplayD3DPicture(vout_display_sys_t
*sys
, d3d_quad_t
*quad
)
794 UINT stride
= sizeof(d3d_vertex_t
);
797 /* Render the quad */
798 ID3D11DeviceContext_PSSetShader(sys
->d3dcontext
, quad
->d3dpixelShader
, NULL
, 0);
799 ID3D11DeviceContext_PSSetShaderResources(sys
->d3dcontext
, 0, 1, &quad
->d3dresViewY
);
801 if( quad
->d3dresViewUV
)
802 ID3D11DeviceContext_PSSetShaderResources(sys
->d3dcontext
, 1, 1, &quad
->d3dresViewUV
);
804 ID3D11DeviceContext_IASetVertexBuffers(sys
->d3dcontext
, 0, 1, &quad
->pVertexBuffer
, &stride
, &offset
);
805 ID3D11DeviceContext_DrawIndexed(sys
->d3dcontext
, 6, 0, 0);
808 static void Display(vout_display_t
*vd
, picture_t
*picture
, subpicture_t
*subpicture
)
810 vout_display_sys_t
*sys
= vd
->sys
;
812 FLOAT blackRGBA
[4] = {0.0f
, 0.0f
, 0.0f
, 1.0f
};
813 ID3D11DeviceContext_ClearRenderTargetView(sys
->d3dcontext
, sys
->d3drenderTargetView
, blackRGBA
);
815 /* no ID3D11Device operations should come here */
817 ID3D11DeviceContext_OMSetRenderTargets(sys
->d3dcontext
, 1, &sys
->d3drenderTargetView
, sys
->d3ddepthStencilView
);
819 ID3D11DeviceContext_ClearDepthStencilView(sys
->d3dcontext
, sys
->d3ddepthStencilView
, D3D11_CLEAR_DEPTH
| D3D11_CLEAR_STENCIL
, 1.0f
, 0);
821 /* Render the quad */
822 DisplayD3DPicture(sys
, &sys
->picQuad
);
825 // draw the additional vertices
826 for (int i
= 0; i
< sys
->d3dregion_count
; ++i
) {
827 DisplayD3DPicture(sys
, (d3d_quad_t
*) sys
->d3dregions
[i
]->p_sys
);
831 HRESULT hr
= IDXGISwapChain_Present(sys
->dxgiswapChain
, 0, 0);
832 if (hr
== DXGI_ERROR_DEVICE_REMOVED
|| hr
== DXGI_ERROR_DEVICE_RESET
)
834 /* TODO device lost */
837 picture_Release(picture
);
839 subpicture_Delete(subpicture
);
844 static void Direct3D11Destroy(vout_display_t
*vd
)
846 #if !VLC_WINSTORE_APP
847 vout_display_sys_t
*sys
= vd
->sys
;
851 FreeLibrary(sys
->hdxgi_dll
);
855 FreeLibrary(sys
->hd3d11_dll
);
856 if (sys
->hd3dcompiler_dll
)
857 FreeLibrary(sys
->hd3dcompiler_dll
);
859 /* TODO : add release of d3d11 objects here */
861 sys
->OurD3D11CreateDevice
= NULL
;
862 sys
->OurD3D11CreateDeviceAndSwapChain
= NULL
;
863 sys
->OurD3DCompile
= NULL
;
864 sys
->hdxgi_dll
= NULL
;
865 sys
->hd3d11_dll
= NULL
;
866 sys
->hd3dcompiler_dll
= NULL
;
872 #if !VLC_WINSTORE_APP
873 static HINSTANCE
Direct3D11LoadShaderLibrary(void)
875 HINSTANCE instance
= NULL
;
876 /* d3dcompiler_47 is the latest on windows 8.1 */
877 for (int i
= 47; i
> 41; --i
) {
879 _sntprintf(filename
, 19, TEXT("D3DCOMPILER_%d.dll"), i
);
880 instance
= LoadLibrary(filename
);
888 static int Direct3D11Open(vout_display_t
*vd
, video_format_t
*fmt
)
890 vout_display_sys_t
*sys
= vd
->sys
;
893 #if !VLC_WINSTORE_APP
895 UINT creationFlags
= 0;
898 # if !defined(NDEBUG) && defined(_MSC_VER)
899 creationFlags
|= D3D11_CREATE_DEVICE_DEBUG
;
902 DXGI_SWAP_CHAIN_DESC scd
;
903 memset(&scd
, 0, sizeof(scd
));
905 scd
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
906 scd
.SampleDesc
.Count
= 1;
907 scd
.SampleDesc
.Quality
= 0;
908 scd
.BufferDesc
.Width
= fmt
->i_visible_width
;
909 scd
.BufferDesc
.Height
= fmt
->i_visible_height
;
910 scd
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
913 scd
.OutputWindow
= sys
->hvideownd
;
915 IDXGIAdapter
*dxgiadapter
;
917 static const D3D_FEATURE_LEVEL featureLevels
[] =
919 D3D_FEATURE_LEVEL_11_1
,
920 D3D_FEATURE_LEVEL_11_0
,
921 D3D_FEATURE_LEVEL_10_1
,
922 D3D_FEATURE_LEVEL_10_0
,
923 D3D_FEATURE_LEVEL_9_3
,
924 D3D_FEATURE_LEVEL_9_2
,
925 D3D_FEATURE_LEVEL_9_1
928 /* TODO : list adapters for the user to choose from */
929 hr
= IDXGIFactory_EnumAdapters(sys
->dxgifactory
, 0, &dxgiadapter
);
931 msg_Err(vd
, "Could not create find factory. (hr=0x%lX)", hr
);
936 hr
= IDXGIAdapter_EnumOutputs(dxgiadapter
, 0, &output
);
938 msg_Err(vd
, "Could not Enumerate DXGI Outputs. (hr=0x%lX)", hr
);
939 IDXGIAdapter_Release(dxgiadapter
);
944 memset(&md
, 0, sizeof(md
));
945 md
.Width
= fmt
->i_visible_width
;
946 md
.Height
= fmt
->i_visible_height
;
947 md
.Format
= scd
.BufferDesc
.Format
;
948 md
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
950 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &md
, &scd
.BufferDesc
, NULL
);
952 msg_Err(vd
, "Failed to find a supported video mode. (hr=0x%lX)", hr
);
953 IDXGIAdapter_Release(dxgiadapter
);
957 /* mode desc doesn't carry over the width and height*/
958 scd
.BufferDesc
.Width
= fmt
->i_visible_width
;
959 scd
.BufferDesc
.Height
= fmt
->i_visible_height
;
961 hr
= D3D11CreateDeviceAndSwapChain(dxgiadapter
,
962 D3D_DRIVER_TYPE_UNKNOWN
, NULL
, creationFlags
,
963 featureLevels
, ARRAYSIZE(featureLevels
),
964 D3D11_SDK_VERSION
, &scd
, &sys
->dxgiswapChain
,
965 &sys
->d3ddevice
, NULL
, &sys
->d3dcontext
);
966 IDXGIAdapter_Release(dxgiadapter
);
968 msg_Err(vd
, "Could not Create the D3D11 device and SwapChain. (hr=0x%lX)", hr
);
974 static const D3D_DRIVER_TYPE driverAttempts
[] = {
975 D3D_DRIVER_TYPE_HARDWARE
,
976 D3D_DRIVER_TYPE_WARP
,
977 D3D_DRIVER_TYPE_REFERENCE
,
980 for (UINT driver
= 0; driver
< ARRAYSIZE(driverAttempts
); driver
++) {
981 hr
= D3D11CreateDevice(NULL
, driverAttempts
[driver
], NULL
, creationFlags
,
982 NULL
, 0, D3D11_SDK_VERSION
,
983 &sys
->d3ddevice
, NULL
, &sys
->d3dcontext
);
986 msg_Dbg(vd
, "Created the D3D11 device 0x%p ctx 0x%p type %d.", sys
->d3ddevice
, sys
->d3dcontext
, driverAttempts
[driver
]);
993 msg_Err(vd
, "Could not Create the D3D11 device. (hr=0x%lX)", hr
);
997 IDXGIDevice
*pDXGIDevice
= NULL
;
998 hr
= ID3D11Device_QueryInterface(sys
->d3ddevice
, &IID_IDXGIDevice
, (void **)&pDXGIDevice
);
1000 msg_Err(vd
, "Could not Query DXGI Interface. (hr=0x%lX)", hr
);
1001 return VLC_EGENERIC
;
1004 hr
= IDXGIDevice_GetAdapter(pDXGIDevice
, &dxgiadapter
);
1005 IDXGIAdapter_Release(pDXGIDevice
);
1007 msg_Err(vd
, "Could not get the DXGI Adapter. (hr=0x%lX)", hr
);
1008 return VLC_EGENERIC
;
1011 hr
= IDXGIAdapter_GetParent(dxgiadapter
, &IID_IDXGIFactory
, (void **)&sys
->dxgifactory
);
1012 IDXGIAdapter_Release(dxgiadapter
);
1014 msg_Err(vd
, "Could not get the DXGI Factory. (hr=0x%lX)", hr
);
1015 return VLC_EGENERIC
;
1018 hr
= IDXGIFactory_CreateSwapChain(sys
->dxgifactory
, (IUnknown
*)sys
->d3ddevice
, &scd
, &sys
->dxgiswapChain
);
1019 IDXGIFactory_Release(sys
->dxgifactory
);
1021 msg_Err(vd
, "Could not create the SwapChain. (hr=0x%lX)", hr
);
1022 return VLC_EGENERIC
;
1028 vlc_fourcc_t i_src_chroma
= fmt
->i_chroma
;
1031 // look for the request pixel format first
1032 UINT i_quadSupportFlags
= D3D11_FORMAT_SUPPORT_TEXTURE2D
| D3D11_FORMAT_SUPPORT_SHADER_LOAD
;
1033 UINT i_formatSupport
;
1034 for (unsigned i
= 0; d3d_formats
[i
].name
!= 0; i
++)
1036 if( i_src_chroma
== d3d_formats
[i
].fourcc
)
1038 if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys
->d3ddevice
,
1039 d3d_formats
[i
].formatTexture
,
1040 &i_formatSupport
)) &&
1041 ( i_formatSupport
& i_quadSupportFlags
) == i_quadSupportFlags
)
1043 msg_Dbg(vd
, "Using pixel format %s", d3d_formats
[i
].name
);
1044 fmt
->i_chroma
= d3d_formats
[i
].fourcc
;
1045 sys
->picQuadConfig
.textureFormat
= d3d_formats
[i
].formatTexture
;
1046 sys
->picQuadConfig
.resourceFormatYRGB
= d3d_formats
[i
].formatY
;
1047 sys
->picQuadConfig
.resourceFormatUV
= d3d_formats
[i
].formatUV
;
1053 // look for any pixel format that we can handle
1054 if ( !fmt
->i_chroma
)
1056 for (unsigned i
= 0; d3d_formats
[i
].name
!= 0; i
++)
1058 if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys
->d3ddevice
,
1059 d3d_formats
[i
].formatTexture
,
1060 &i_formatSupport
)) &&
1061 ( i_formatSupport
& i_quadSupportFlags
) == i_quadSupportFlags
)
1063 msg_Dbg(vd
, "Using pixel format %s", d3d_formats
[i
].name
);
1064 fmt
->i_chroma
= d3d_formats
[i
].fourcc
;
1065 sys
->picQuadConfig
.textureFormat
= d3d_formats
[i
].formatTexture
;
1066 sys
->picQuadConfig
.resourceFormatYRGB
= d3d_formats
[i
].formatY
;
1067 sys
->picQuadConfig
.resourceFormatUV
= d3d_formats
[i
].formatUV
;
1072 if ( !fmt
->i_chroma
)
1074 msg_Err(vd
, "Could not get a suitable texture pixel format");
1075 return VLC_EGENERIC
;
1078 /* check the region pixel format */
1079 i_quadSupportFlags
|= D3D11_FORMAT_SUPPORT_BLENDABLE
;
1080 if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys
->d3ddevice
,
1081 DXGI_FORMAT_R8G8B8A8_UNORM
,
1082 &i_formatSupport
)) &&
1083 ( i_formatSupport
& i_quadSupportFlags
) == i_quadSupportFlags
) {
1084 sys
->d3dregion_format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1085 sys
->pSubpictureChromas
[0] = VLC_CODEC_RGBA
;
1086 sys
->pSubpictureChromas
[1] = 0;
1087 } else if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys
->d3ddevice
,
1088 DXGI_FORMAT_B8G8R8A8_UNORM
,
1089 &i_formatSupport
)) &&
1090 ( i_formatSupport
& i_quadSupportFlags
) == i_quadSupportFlags
) {
1091 sys
->d3dregion_format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
1092 sys
->pSubpictureChromas
[0] = VLC_CODEC_BGRA
;
1093 sys
->pSubpictureChromas
[1] = 0;
1095 sys
->d3dregion_format
= DXGI_FORMAT_UNKNOWN
;
1098 switch (fmt
->i_chroma
)
1100 case VLC_CODEC_NV12
:
1101 case VLC_CODEC_D3D11_OPAQUE
:
1102 if( fmt
->i_height
> 576 )
1103 sys
->d3dPxShader
= globPixelShaderBiplanarYUV_BT709_2RGB
;
1105 sys
->d3dPxShader
= globPixelShaderBiplanarYUV_BT601_2RGB
;
1107 case VLC_CODEC_YV12
:
1108 case VLC_CODEC_I420
:
1109 if( fmt
->i_height
> 576 )
1110 sys
->d3dPxShader
= globPixelShaderBiplanarI420_BT709_2RGB
;
1112 sys
->d3dPxShader
= globPixelShaderBiplanarI420_BT601_2RGB
;
1114 case VLC_CODEC_RGB32
:
1115 case VLC_CODEC_BGRA
:
1116 case VLC_CODEC_RGB16
:
1118 sys
->d3dPxShader
= globPixelShaderDefault
;
1121 if (sys
->d3dregion_format
!= DXGI_FORMAT_UNKNOWN
)
1122 sys
->psz_rgbaPxShader
= globPixelShaderDefault
;
1124 sys
->psz_rgbaPxShader
= NULL
;
1126 UpdateRects(vd
, NULL
, NULL
, true);
1128 if (Direct3D11CreateResources(vd
, fmt
)) {
1129 msg_Err(vd
, "Failed to allocate resources");
1130 Direct3D11DestroyResources(vd
);
1131 return VLC_EGENERIC
;
1134 #if !VLC_WINSTORE_APP
1135 EventThreadUpdateTitle(sys
->event
, VOUT_TITLE
" (Direct3D11 output)");
1138 msg_Dbg(vd
, "Direct3D11 device adapter successfully initialized");
1142 static void Direct3D11Close(vout_display_t
*vd
)
1144 vout_display_sys_t
*sys
= vd
->sys
;
1146 Direct3D11DestroyResources(vd
);
1147 if (sys
->d3dcontext
)
1149 ID3D11DeviceContext_Flush(sys
->d3dcontext
);
1150 ID3D11DeviceContext_Release(sys
->d3dcontext
);
1151 sys
->d3dcontext
= NULL
;
1155 ID3D11Device_Release(sys
->d3ddevice
);
1156 sys
->d3ddevice
= NULL
;
1158 if (sys
->dxgiswapChain
)
1160 IDXGISwapChain_Release(sys
->dxgiswapChain
);
1161 sys
->dxgiswapChain
= NULL
;
1164 msg_Dbg(vd
, "Direct3D11 device adapter closed");
1167 static void UpdatePicQuadPosition(vout_display_t
*vd
)
1169 vout_display_sys_t
*sys
= vd
->sys
;
1170 int i_width
= RECTWidth(sys
->rect_dest_clipped
);
1171 int i_height
= RECTHeight(sys
->rect_dest_clipped
);
1172 #if VLC_WINSTORE_APP
1173 UINT dataSize
= sizeof(i_width
);
1174 HRESULT hr
= IDXGISwapChain_GetPrivateData(sys
->dxgiswapChain
, &GUID_SWAPCHAIN_WIDTH
, &dataSize
, &i_width
);
1176 msg_Err(vd
, "Can't get swapchain width, size %d. (hr=0x%lX)", hr
, dataSize
);
1179 dataSize
= sizeof(i_height
);
1180 hr
= IDXGISwapChain_GetPrivateData(sys
->dxgiswapChain
, &GUID_SWAPCHAIN_HEIGHT
, &dataSize
, &i_height
);
1182 msg_Err(vd
, "Can't get swapchain height, size %d. (hr=0x%lX)", hr
, dataSize
);
1187 /* Map the subpicture to sys->rect_dest_clipped */
1188 UpdateQuadPosition(vd
, &sys
->picQuad
, &sys
->rect_dest_clipped
, i_width
, i_height
, 1.0f
);
1191 /* TODO : handle errors better
1192 TODO : seperate out into smaller functions like createshaders */
1193 static int Direct3D11CreateResources(vout_display_t
*vd
, video_format_t
*fmt
)
1195 vout_display_sys_t
*sys
= vd
->sys
;
1198 hr
= UpdateBackBuffer(vd
);
1200 msg_Err(vd
, "Could not update the backbuffer. (hr=0x%lX)", hr
);
1201 return VLC_EGENERIC
;
1204 ID3D11BlendState
*pSpuBlendState
;
1205 D3D11_BLEND_DESC spuBlendDesc
= { 0 };
1206 spuBlendDesc
.RenderTarget
[0].BlendEnable
= TRUE
;
1207 spuBlendDesc
.RenderTarget
[0].SrcBlend
= D3D11_BLEND_SRC_ALPHA
;
1208 spuBlendDesc
.RenderTarget
[0].DestBlend
= D3D11_BLEND_INV_SRC_ALPHA
;
1209 spuBlendDesc
.RenderTarget
[0].BlendOp
= D3D11_BLEND_OP_ADD
;
1211 spuBlendDesc
.RenderTarget
[0].SrcBlendAlpha
= D3D11_BLEND_ONE
;
1212 spuBlendDesc
.RenderTarget
[0].DestBlendAlpha
= D3D11_BLEND_ZERO
;
1213 spuBlendDesc
.RenderTarget
[0].BlendOpAlpha
= D3D11_BLEND_OP_ADD
;
1215 spuBlendDesc
.RenderTarget
[0].RenderTargetWriteMask
= D3D11_COLOR_WRITE_ENABLE_ALL
;
1217 spuBlendDesc
.RenderTarget
[1].BlendEnable
= TRUE
;
1218 spuBlendDesc
.RenderTarget
[1].SrcBlend
= D3D11_BLEND_ONE
;
1219 spuBlendDesc
.RenderTarget
[1].DestBlend
= D3D11_BLEND_ZERO
;
1220 spuBlendDesc
.RenderTarget
[1].BlendOp
= D3D11_BLEND_OP_ADD
;
1222 spuBlendDesc
.RenderTarget
[1].SrcBlendAlpha
= D3D11_BLEND_ONE
;
1223 spuBlendDesc
.RenderTarget
[1].DestBlendAlpha
= D3D11_BLEND_ZERO
;
1224 spuBlendDesc
.RenderTarget
[1].BlendOpAlpha
= D3D11_BLEND_OP_ADD
;
1226 spuBlendDesc
.RenderTarget
[1].RenderTargetWriteMask
= D3D11_COLOR_WRITE_ENABLE_ALL
;
1227 hr
= ID3D11Device_CreateBlendState(sys
->d3ddevice
, &spuBlendDesc
, &pSpuBlendState
);
1229 msg_Err(vd
, "Could not create SPU blend state. (hr=0x%lX)", hr
);
1230 return VLC_EGENERIC
;
1232 ID3D11DeviceContext_OMSetBlendState(sys
->d3dcontext
, pSpuBlendState
, NULL
, 0xFFFFFFFF);
1233 ID3D11BlendState_Release(pSpuBlendState
);
1235 /* disable depth testing as we're only doing 2D
1236 * see https://msdn.microsoft.com/en-us/library/windows/desktop/bb205074%28v=vs.85%29.aspx
1237 * see http://rastertek.com/dx11tut11.html
1239 D3D11_DEPTH_STENCIL_DESC stencilDesc
;
1240 ZeroMemory(&stencilDesc
, sizeof(stencilDesc
));
1241 stencilDesc
.DepthEnable
= FALSE
;
1242 stencilDesc
.StencilEnable
= TRUE
;
1243 stencilDesc
.DepthWriteMask
= D3D11_DEPTH_WRITE_MASK_ALL
;
1244 stencilDesc
.DepthFunc
= D3D11_COMPARISON_LESS
;
1245 stencilDesc
.StencilReadMask
= 0xFF;
1246 stencilDesc
.StencilWriteMask
= 0xFF;
1247 stencilDesc
.FrontFace
.StencilFailOp
= D3D11_STENCIL_OP_KEEP
;
1248 stencilDesc
.FrontFace
.StencilDepthFailOp
= D3D11_STENCIL_OP_INCR
;
1249 stencilDesc
.FrontFace
.StencilPassOp
= D3D11_STENCIL_OP_KEEP
;
1250 stencilDesc
.FrontFace
.StencilFunc
= D3D11_COMPARISON_ALWAYS
;
1251 stencilDesc
.BackFace
.StencilFailOp
= D3D11_STENCIL_OP_KEEP
;
1252 stencilDesc
.BackFace
.StencilDepthFailOp
= D3D11_STENCIL_OP_DECR
;
1253 stencilDesc
.BackFace
.StencilPassOp
= D3D11_STENCIL_OP_KEEP
;
1254 stencilDesc
.BackFace
.StencilFunc
= D3D11_COMPARISON_ALWAYS
;
1256 ID3D11DepthStencilState
*pDepthStencilState
;
1257 hr
= ID3D11Device_CreateDepthStencilState(sys
->d3ddevice
, &stencilDesc
, &pDepthStencilState
);
1258 if (SUCCEEDED(hr
)) {
1259 ID3D11DeviceContext_OMSetDepthStencilState(sys
->d3dcontext
, pDepthStencilState
, 0);
1260 ID3D11DepthStencilState_Release(pDepthStencilState
);
1263 ID3DBlob
* pVSBlob
= NULL
;
1265 /* TODO : Match the version to the D3D_FEATURE_LEVEL */
1266 hr
= D3DCompile(globVertexShaderDefault
, strlen(globVertexShaderDefault
),
1267 NULL
, NULL
, NULL
, "VS", "vs_4_0_level_9_1", 0, 0, &pVSBlob
, NULL
);
1270 msg_Err(vd
, "The Vertex Shader is invalid.");
1271 return VLC_EGENERIC
;
1274 ID3D11VertexShader
*d3dvertexShader
;
1275 hr
= ID3D11Device_CreateVertexShader(sys
->d3ddevice
, (void *)ID3D10Blob_GetBufferPointer(pVSBlob
),
1276 ID3D10Blob_GetBufferSize(pVSBlob
), NULL
, &d3dvertexShader
);
1279 ID3D11Device_Release(pVSBlob
);
1280 msg_Err(vd
, "Failed to create the vertex shader.");
1281 return VLC_EGENERIC
;
1283 ID3D11DeviceContext_VSSetShader(sys
->d3dcontext
, d3dvertexShader
, NULL
, 0);
1284 ID3D11VertexShader_Release(d3dvertexShader
);
1286 D3D11_INPUT_ELEMENT_DESC layout
[] = {
1287 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT
, 0, 0, D3D11_INPUT_PER_VERTEX_DATA
, 0},
1288 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 12, D3D11_INPUT_PER_VERTEX_DATA
, 0},
1289 { "OPACITY", 0, DXGI_FORMAT_R32_FLOAT
, 0, 20, D3D11_INPUT_PER_VERTEX_DATA
, 0},
1292 ID3D11InputLayout
* pVertexLayout
= NULL
;
1293 hr
= ID3D11Device_CreateInputLayout(sys
->d3ddevice
, layout
, 3, (void *)ID3D10Blob_GetBufferPointer(pVSBlob
),
1294 ID3D10Blob_GetBufferSize(pVSBlob
), &pVertexLayout
);
1296 ID3D10Blob_Release(pVSBlob
);
1299 msg_Err(vd
, "Failed to create the vertex input layout");
1300 return VLC_EGENERIC
;
1303 ID3D11DeviceContext_IASetInputLayout(sys
->d3dcontext
, pVertexLayout
);
1304 ID3D11SamplerState_Release(pVertexLayout
);
1306 /* create the index of the vertices */
1312 D3D11_BUFFER_DESC quadDesc
= {
1313 .Usage
= D3D11_USAGE_DEFAULT
,
1314 .ByteWidth
= sizeof(WORD
) * 6,
1315 .BindFlags
= D3D11_BIND_INDEX_BUFFER
,
1316 .CPUAccessFlags
= 0,
1319 D3D11_SUBRESOURCE_DATA quadIndicesInit
= {
1323 ID3D11Buffer
* pIndexBuffer
= NULL
;
1324 hr
= ID3D11Device_CreateBuffer(sys
->d3ddevice
, &quadDesc
, &quadIndicesInit
, &pIndexBuffer
);
1326 msg_Err(vd
, "Could not Create the common quad indices. (hr=0x%lX)", hr
);
1327 return VLC_EGENERIC
;
1329 ID3D11DeviceContext_IASetIndexBuffer(sys
->d3dcontext
, pIndexBuffer
, DXGI_FORMAT_R16_UINT
, 0);
1330 ID3D11Buffer_Release(pIndexBuffer
);
1332 ID3D11DeviceContext_IASetPrimitiveTopology(sys
->d3dcontext
, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);
1334 ID3DBlob
* pPSBlob
= NULL
;
1336 /* TODO : Match the version to the D3D_FEATURE_LEVEL */
1337 hr
= D3DCompile(sys
->d3dPxShader
, strlen(sys
->d3dPxShader
),
1338 NULL
, NULL
, NULL
, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob
, NULL
);
1342 msg_Err(vd
, "The Pixel Shader is invalid. (hr=0x%lX)", hr
);
1343 return VLC_EGENERIC
;
1346 ID3D11PixelShader
*pPicQuadShader
;
1347 hr
= ID3D11Device_CreatePixelShader(sys
->d3ddevice
, (void *)ID3D10Blob_GetBufferPointer(pPSBlob
),
1348 ID3D10Blob_GetBufferSize(pPSBlob
), NULL
, &pPicQuadShader
);
1350 ID3D10Blob_Release(pPSBlob
);
1353 msg_Err(vd
, "Failed to create the pixel shader.");
1354 return VLC_EGENERIC
;
1357 if (sys
->psz_rgbaPxShader
!= NULL
)
1359 hr
= D3DCompile(sys
->psz_rgbaPxShader
, strlen(sys
->psz_rgbaPxShader
),
1360 NULL
, NULL
, NULL
, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob
, NULL
);
1362 ID3D11PixelShader_Release(pPicQuadShader
);
1363 msg_Err(vd
, "The RGBA Pixel Shader is invalid. (hr=0x%lX)", hr
);
1364 return VLC_EGENERIC
;
1367 hr
= ID3D11Device_CreatePixelShader(sys
->d3ddevice
, (void *)ID3D10Blob_GetBufferPointer(pPSBlob
),
1368 ID3D10Blob_GetBufferSize(pPSBlob
), NULL
, &sys
->pSPUPixelShader
);
1370 ID3D10Blob_Release(pPSBlob
);
1373 ID3D11PixelShader_Release(pPicQuadShader
);
1374 msg_Err(vd
, "Failed to create the SPU pixel shader.");
1375 return VLC_EGENERIC
;
1379 if (AllocQuad( vd
, fmt
, &sys
->picQuad
, &sys
->picQuadConfig
, pPicQuadShader
) != VLC_SUCCESS
) {
1380 ID3D11PixelShader_Release(pPicQuadShader
);
1381 msg_Err(vd
, "Could not Create the main quad picture. (hr=0x%lX)", hr
);
1382 return VLC_EGENERIC
;
1384 ID3D11PixelShader_Release(pPicQuadShader
);
1386 UpdatePicQuadPosition(vd
);
1388 D3D11_SAMPLER_DESC sampDesc
;
1389 memset(&sampDesc
, 0, sizeof(sampDesc
));
1390 sampDesc
.Filter
= D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT
;
1391 sampDesc
.AddressU
= D3D11_TEXTURE_ADDRESS_WRAP
;
1392 sampDesc
.AddressV
= D3D11_TEXTURE_ADDRESS_WRAP
;
1393 sampDesc
.AddressW
= D3D11_TEXTURE_ADDRESS_WRAP
;
1394 sampDesc
.ComparisonFunc
= D3D11_COMPARISON_ALWAYS
;
1395 sampDesc
.MinLOD
= 0;
1396 sampDesc
.MaxLOD
= D3D11_FLOAT32_MAX
;
1398 ID3D11SamplerState
*d3dsampState
;
1399 hr
= ID3D11Device_CreateSamplerState(sys
->d3ddevice
, &sampDesc
, &d3dsampState
);
1402 msg_Err(vd
, "Could not Create the D3d11 Sampler State. (hr=0x%lX)", hr
);
1403 return VLC_EGENERIC
;
1405 ID3D11DeviceContext_PSSetSamplers(sys
->d3dcontext
, 0, 1, &d3dsampState
);
1406 ID3D11SamplerState_Release(d3dsampState
);
1408 if (Direct3D11CreatePool(vd
, fmt
))
1410 msg_Err(vd
, "Direct3D picture pool initialization failed");
1411 return VLC_EGENERIC
;
1414 msg_Dbg(vd
, "Direct3D11 resources created");
1418 static int Direct3D11CreatePool(vout_display_t
*vd
, video_format_t
*fmt
)
1420 vout_display_sys_t
*sys
= vd
->sys
;
1422 if ( fmt
->i_chroma
== VLC_CODEC_D3D11_OPAQUE
)
1423 /* a D3D11VA pool will be created when needed */
1426 picture_sys_pool_t
*picsys
= calloc(1, sizeof(*picsys
));
1427 if (unlikely(picsys
== NULL
)) {
1431 picsys
->texture
= sys
->picQuad
.pTexture
;
1434 picture_resource_t resource
= {
1435 .p_sys
= (picture_sys_t
*) picsys
,
1436 .pf_destroy
= DestroyDisplayPicture
,
1439 picture_t
*picture
= picture_NewFromResource(fmt
, &resource
);
1444 ID3D11Texture2D_AddRef(picsys
->texture
);
1446 picture_pool_configuration_t pool_cfg
;
1447 memset(&pool_cfg
, 0, sizeof(pool_cfg
));
1448 pool_cfg
.picture_count
= 1;
1449 pool_cfg
.picture
= &picture
;
1450 pool_cfg
.lock
= Direct3D11MapTexture
;
1452 sys
->pool
= picture_pool_NewExtended(&pool_cfg
);
1454 picture_Release(picture
);
1461 static void Direct3D11DestroyPool(vout_display_t
*vd
)
1463 vout_display_sys_t
*sys
= vd
->sys
;
1466 picture_pool_Release(sys
->pool
);
1470 static int AllocQuad(vout_display_t
*vd
, const video_format_t
*fmt
, d3d_quad_t
*quad
,
1471 d3d_quad_cfg_t
*cfg
, ID3D11PixelShader
*d3dpixelShader
)
1473 vout_display_sys_t
*sys
= vd
->sys
;
1476 D3D11_BUFFER_DESC bd
;
1477 memset(&bd
, 0, sizeof(bd
));
1478 bd
.Usage
= D3D11_USAGE_DYNAMIC
;
1479 bd
.ByteWidth
= sizeof(d3d_vertex_t
) * 4;
1480 bd
.BindFlags
= D3D11_BIND_VERTEX_BUFFER
;
1481 bd
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
;
1483 hr
= ID3D11Device_CreateBuffer(sys
->d3ddevice
, &bd
, NULL
, &quad
->pVertexBuffer
);
1485 msg_Err(vd
, "Failed to create vertex buffer.");
1489 D3D11_TEXTURE2D_DESC texDesc
;
1490 memset(&texDesc
, 0, sizeof(texDesc
));
1491 texDesc
.Width
= fmt
->i_visible_width
;
1492 texDesc
.Height
= fmt
->i_visible_height
;
1493 texDesc
.MipLevels
= texDesc
.ArraySize
= 1;
1494 texDesc
.Format
= cfg
->textureFormat
;
1495 texDesc
.SampleDesc
.Count
= 1;
1496 texDesc
.Usage
= D3D11_USAGE_DYNAMIC
;
1497 texDesc
.BindFlags
= D3D11_BIND_SHADER_RESOURCE
;
1498 texDesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
;
1499 texDesc
.MiscFlags
= 0;
1501 hr
= ID3D11Device_CreateTexture2D(sys
->d3ddevice
, &texDesc
, NULL
, &quad
->pTexture
);
1503 msg_Err(vd
, "Could not Create the D3d11 Texture. (hr=0x%lX)", hr
);
1507 D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc
;
1508 memset(&resviewDesc
, 0, sizeof(resviewDesc
));
1509 resviewDesc
.Format
= cfg
->resourceFormatYRGB
;
1510 resviewDesc
.ViewDimension
= D3D11_SRV_DIMENSION_TEXTURE2D
;
1511 resviewDesc
.Texture2D
.MipLevels
= texDesc
.MipLevels
;
1513 hr
= ID3D11Device_CreateShaderResourceView(sys
->d3ddevice
, (ID3D11Resource
*)quad
->pTexture
, &resviewDesc
, &quad
->d3dresViewY
);
1515 msg_Err(vd
, "Could not Create the Y/RGB D3d11 Texture ResourceView. (hr=0x%lX)", hr
);
1519 if( cfg
->resourceFormatUV
)
1521 resviewDesc
.Format
= cfg
->resourceFormatUV
;
1522 hr
= ID3D11Device_CreateShaderResourceView(sys
->d3ddevice
, (ID3D11Resource
*)quad
->pTexture
, &resviewDesc
, &quad
->d3dresViewUV
);
1524 msg_Err(vd
, "Could not Create the UV D3d11 Texture ResourceView. (hr=0x%lX)", hr
);
1529 quad
->d3dpixelShader
= d3dpixelShader
;
1530 ID3D11PixelShader_AddRef(quad
->d3dpixelShader
);
1536 return VLC_EGENERIC
;
1539 static void ReleaseQuad(d3d_quad_t
*quad
)
1541 if (quad
->pVertexBuffer
)
1542 ID3D11Buffer_Release(quad
->pVertexBuffer
);
1544 ID3D11Texture2D_Release(quad
->pTexture
);
1545 if (quad
->d3dresViewY
)
1546 ID3D11ShaderResourceView_Release(quad
->d3dresViewY
);
1547 if (quad
->d3dresViewUV
)
1548 ID3D11ShaderResourceView_Release(quad
->d3dresViewUV
);
1549 if (quad
->d3dpixelShader
)
1550 ID3D11VertexShader_Release(quad
->d3dpixelShader
);
1553 static void Direct3D11DestroyResources(vout_display_t
*vd
)
1555 vout_display_sys_t
*sys
= vd
->sys
;
1557 Direct3D11DestroyPool(vd
);
1559 ReleaseQuad(&sys
->picQuad
);
1560 Direct3D11DeleteRegions(sys
->d3dregion_count
, sys
->d3dregions
);
1561 sys
->d3dregion_count
= 0;
1563 if (sys
->d3drenderTargetView
)
1564 ID3D11RenderTargetView_Release(sys
->d3drenderTargetView
);
1565 if (sys
->d3ddepthStencilView
)
1566 ID3D11DepthStencilView_Release(sys
->d3ddepthStencilView
);
1567 if (sys
->pSPUPixelShader
)
1568 ID3D11VertexShader_Release(sys
->pSPUPixelShader
);
1570 msg_Dbg(vd
, "Direct3D11 resources destroyed");
1573 static int Direct3D11MapTexture(picture_t
*picture
)
1575 picture_sys_pool_t
*p_sys
= (picture_sys_pool_t
*) picture
->p_sys
;
1576 vout_display_t
*vd
= p_sys
->vd
;
1577 D3D11_MAPPED_SUBRESOURCE mappedResource
;
1580 hr
= ID3D11DeviceContext_Map(vd
->sys
->d3dcontext
, (ID3D11Resource
*)p_sys
->texture
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &mappedResource
);
1583 msg_Dbg( vd
, "failed to map the texture (hr=0x%lX)", hr
);
1584 return VLC_EGENERIC
;
1586 res
= CommonUpdatePicture(picture
, NULL
, mappedResource
.pData
, mappedResource
.RowPitch
);
1587 ID3D11DeviceContext_Unmap(vd
->sys
->d3dcontext
,(ID3D11Resource
*)p_sys
->texture
, 0);
1591 static void Direct3D11DeleteRegions(int count
, picture_t
**region
)
1593 for (int i
= 0; i
< count
; ++i
) {
1595 picture_Release(region
[i
]);
1601 static void DestroyPictureQuad(picture_t
*p_picture
)
1603 ReleaseQuad( (d3d_quad_t
*) p_picture
->p_sys
);
1607 static void UpdateQuadPosition(vout_display_t
*vd
, const d3d_quad_t
*quad
, const RECT
*dst
, int i_width
, int i_height
, float opacity
)
1609 vout_display_sys_t
*sys
= vd
->sys
;
1610 D3D11_MAPPED_SUBRESOURCE mappedResource
;
1612 // adjust with the center at 0,0 and the edges at -1/1
1613 float left
= -1.0f
+ 2.0f
* ((float) dst
->left
/ i_width
);
1614 float right
= -1.0f
+ 2.0f
* ((float) dst
->right
/ i_width
);
1615 float top
= 1.0f
- 2.0f
* ((float) dst
->top
/ i_height
);
1616 float bottom
= 1.0f
- 2.0f
* ((float) dst
->bottom
/ i_height
);
1618 HRESULT hr
= ID3D11DeviceContext_Map(sys
->d3dcontext
, (ID3D11Resource
*)quad
->pVertexBuffer
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &mappedResource
);
1619 if (SUCCEEDED(hr
)) {
1620 d3d_vertex_t
*dst_data
= mappedResource
.pData
;
1623 dst_data
[0].position
.x
= left
;
1624 dst_data
[0].position
.y
= bottom
;
1625 dst_data
[0].position
.z
= 0.0f
;
1626 dst_data
[0].texture
.x
= 0.0f
;
1627 dst_data
[0].texture
.y
= 1.0f
;
1628 dst_data
[0].opacity
= opacity
;
1631 dst_data
[1].position
.x
= right
;
1632 dst_data
[1].position
.y
= bottom
;
1633 dst_data
[1].position
.z
= 0.0f
;
1634 dst_data
[1].texture
.x
= 1.0f
;
1635 dst_data
[1].texture
.y
= 1.0f
;
1636 dst_data
[1].opacity
= opacity
;
1639 dst_data
[2].position
.x
= right
;
1640 dst_data
[2].position
.y
= top
;
1641 dst_data
[2].position
.z
= 0.0f
;
1642 dst_data
[2].texture
.x
= 1.0f
;
1643 dst_data
[2].texture
.y
= 0.0f
;
1644 dst_data
[2].opacity
= opacity
;
1647 dst_data
[3].position
.x
= left
;
1648 dst_data
[3].position
.y
= top
;
1649 dst_data
[3].position
.z
= 0.0f
;
1650 dst_data
[3].texture
.x
= 0.0f
;
1651 dst_data
[3].texture
.y
= 0.0f
;
1652 dst_data
[3].opacity
= opacity
;
1654 ID3D11DeviceContext_Unmap(sys
->d3dcontext
, (ID3D11Resource
*)quad
->pVertexBuffer
, 0);
1657 msg_Err(vd
, "Failed to lock the subpicture vertex buffer (hr=0x%lX)", hr
);
1661 static int Direct3D11MapSubpicture(vout_display_t
*vd
, int *subpicture_region_count
,
1662 picture_t
***region
, subpicture_t
*subpicture
)
1664 vout_display_sys_t
*sys
= vd
->sys
;
1665 D3D11_MAPPED_SUBRESOURCE mappedResource
;
1666 D3D11_TEXTURE2D_DESC texDesc
;
1671 for (subpicture_region_t
*r
= subpicture
->p_region
; r
; r
= r
->p_next
)
1674 *region
= calloc(count
, sizeof(picture_t
*));
1675 if (unlikely(*region
==NULL
))
1677 *subpicture_region_count
= count
;
1680 for (subpicture_region_t
*r
= subpicture
->p_region
; r
; r
= r
->p_next
, i
++) {
1681 for (int j
= 0; j
< sys
->d3dregion_count
; j
++) {
1682 picture_t
*cache
= sys
->d3dregions
[j
];
1683 if (cache
!= NULL
&& ((d3d_quad_t
*) cache
->p_sys
)->pTexture
) {
1684 ID3D11Texture2D_GetDesc( ((d3d_quad_t
*) cache
->p_sys
)->pTexture
, &texDesc
);
1685 if (texDesc
.Format
== sys
->d3dregion_format
&&
1686 texDesc
.Width
== r
->fmt
.i_visible_width
&&
1687 texDesc
.Height
== r
->fmt
.i_visible_height
) {
1688 (*region
)[i
] = cache
;
1689 memset(&sys
->d3dregions
[j
], 0, sizeof(cache
)); // do not reuse this cached value
1695 picture_t
*quad_picture
= (*region
)[i
];
1696 if (quad_picture
== NULL
) {
1697 d3d_quad_t
*d3dquad
= calloc(1, sizeof(*d3dquad
));
1698 if (unlikely(d3dquad
==NULL
)) {
1701 d3d_quad_cfg_t rgbaCfg
= {
1702 .textureFormat
= sys
->d3dregion_format
,
1703 .resourceFormatYRGB
= sys
->d3dregion_format
,
1705 err
= AllocQuad(vd
, &r
->fmt
, d3dquad
, &rgbaCfg
, sys
->pSPUPixelShader
);
1706 if (err
!= VLC_SUCCESS
) {
1707 msg_Err(vd
, "Failed to create %dx%d texture for OSD",
1708 r
->fmt
.i_visible_width
, r
->fmt
.i_visible_height
);
1712 picture_resource_t picres
= {
1713 .p_sys
= (picture_sys_t
*) d3dquad
,
1714 .pf_destroy
= DestroyPictureQuad
,
1716 (*region
)[i
] = picture_NewFromResource(&r
->fmt
, &picres
);
1717 if ((*region
)[i
] == NULL
) {
1718 msg_Err(vd
, "Failed to create %dx%d picture for OSD",
1719 r
->fmt
.i_visible_width
, r
->fmt
.i_visible_height
);
1720 ReleaseQuad(d3dquad
);
1723 quad_picture
= (*region
)[i
];
1724 hr
= ID3D11DeviceContext_Map(sys
->d3dcontext
, (ID3D11Resource
*)((d3d_quad_t
*) quad_picture
->p_sys
)->pTexture
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &mappedResource
);
1725 if( SUCCEEDED(hr
) ) {
1726 err
= CommonUpdatePicture(quad_picture
, NULL
, mappedResource
.pData
, mappedResource
.RowPitch
);
1727 ID3D11DeviceContext_Unmap(sys
->d3dcontext
, (ID3D11Resource
*)((d3d_quad_t
*) quad_picture
->p_sys
)->pTexture
, 0);
1728 if (err
!= VLC_SUCCESS
) {
1729 msg_Err(vd
, "Failed to set the buffer on the OSD picture" );
1730 picture_Release(quad_picture
);
1734 msg_Err(vd
, "Failed to map the OSD texture (hr=0x%lX)", hr
);
1735 picture_Release(quad_picture
);
1739 msg_Dbg(vd
, "Created %dx%d texture for OSD",
1740 r
->fmt
.i_visible_width
, r
->fmt
.i_visible_height
);
1744 picture_CopyPixels(quad_picture
, r
->p_picture
);
1746 /* Map the subpicture to sys->rect_dest */
1747 const int i_original_width
= subpicture
->i_original_picture_width
;
1748 const int i_original_height
= subpicture
->i_original_picture_height
;
1750 const RECT video
= sys
->rect_dest
;
1751 const float scale_w
= (float)(video
.right
- video
.left
) / i_original_width
;
1752 const float scale_h
= (float)(video
.bottom
- video
.top
) / i_original_height
;
1755 dst
.left
= video
.left
+ scale_w
* r
->i_x
,
1756 dst
.right
= dst
.left
+ scale_w
* r
->fmt
.i_visible_width
,
1757 dst
.top
= video
.top
+ scale_h
* r
->i_y
,
1758 dst
.bottom
= dst
.top
+ scale_h
* r
->fmt
.i_visible_height
;
1760 float opacity
= (float)r
->i_alpha
/ 255.0f
;
1762 UpdateQuadPosition(vd
, (d3d_quad_t
*)quad_picture
->p_sys
, &dst
,
1763 i_original_width
, i_original_height
, opacity
);