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>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
27 #include <vlc_common.h>
28 #include <vlc_plugin.h>
29 #include <vlc_vout_display.h>
35 /* avoided until we can pass ISwapchainPanel without c++/cx mode
36 # include <windows.ui.xaml.media.dxinterop.h> */
41 # define D3D11CreateDeviceAndSwapChain(args...) sys->OurD3D11CreateDeviceAndSwapChain(args)
42 # define D3D11CreateDevice(args...) sys->OurD3D11CreateDevice(args)
43 # define D3DCompile(args...) sys->OurD3DCompile(args)
45 # define IDXGISwapChain_Present(args...) IDXGISwapChain_Present1(args)
46 # define IDXGIFactory_CreateSwapChain(a,b,c,d) IDXGIFactory2_CreateSwapChainForComposition(a,b,c,NULL,d)
47 # define DXGI_SWAP_CHAIN_DESC DXGI_SWAP_CHAIN_DESC1
50 static int Open(vlc_object_t *);
51 static void Close(vlc_object_t *);
53 #define D3D11_HELP N_("Recommended video output for Windows 8 and later versions")
56 set_shortname("Direct3D11")
57 set_description(N_("Direct3D11 video output"))
59 set_category(CAT_VIDEO)
60 set_subcategory(SUBCAT_VIDEO_VOUT)
61 set_capability("vout display", 240)
62 add_shortcut("direct3d11")
63 set_callbacks(Open, Close)
69 DXGI_FORMAT formatTexture;
75 static const d3d_format_t d3d_formats[] = {
76 { "NV12", DXGI_FORMAT_NV12, VLC_CODEC_NV12, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
78 { "YUY2", DXGI_FORMAT_YUY2, VLC_CODEC_I422, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
79 { "AYUV", DXGI_FORMAT_AYUV, VLC_CODEC_YUVA, DXGI_FORMAT_R8G8B8A8_UNORM, 0 },
80 { "Y416", DXGI_FORMAT_Y416, VLC_CODEC_I444_16L, DXGI_FORMAT_R16G16B16A16_UINT, 0 },
83 { "P010", DXGI_FORMAT_P010, VLC_CODEC_I420_10L, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM },
84 { "Y210", DXGI_FORMAT_Y210, VLC_CODEC_I422_10L, DXGI_FORMAT_R16G16B16A16_UNORM, 0 },
85 { "Y410", DXGI_FORMAT_Y410, VLC_CODEC_I444_10L, DXGI_FORMAT_R10G10B10A2_UNORM, 0 },
86 { "NV11", DXGI_FORMAT_NV11, VLC_CODEC_I411, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
88 { "R8G8B8X8", DXGI_FORMAT_B8G8R8X8_UNORM, VLC_CODEC_RGB32, DXGI_FORMAT_B8G8R8X8_UNORM, 0 },
89 { "B8G8R8A8", DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_BGRA, DXGI_FORMAT_B8G8R8A8_UNORM, 0 },
90 { "B5G6R5", DXGI_FORMAT_B5G6R5_UNORM, VLC_CODEC_RGB16, DXGI_FORMAT_B5G6R5_UNORM, 0 },
95 static const vlc_fourcc_t d3d_subpicture_chromas[] = {
102 ID3D11Texture2D *texture;
103 ID3D11DeviceContext *context;
107 static int Open(vlc_object_t *);
108 static void Close(vlc_object_t *object);
110 static void Prepare(vout_display_t *, picture_t *, subpicture_t *subpicture);
111 static void Display(vout_display_t *, picture_t *, subpicture_t *subpicture);
113 static HINSTANCE Direct3D11LoadShaderLibrary(void);
114 static void Direct3D11Destroy(vout_display_t *);
116 static int Direct3D11Open (vout_display_t *, video_format_t *);
117 static void Direct3D11Close(vout_display_t *);
119 static int Direct3D11CreateResources (vout_display_t *, video_format_t *);
120 static void Direct3D11DestroyResources(vout_display_t *);
122 static int Direct3D11MapTexture(picture_t *);
124 /* All the #if USE_DXGI contain an alternative method to setup dx11
125 They both need to be benchmarked to see which performs better */
127 /* I have no idea why MS decided dxgi headers do not define this
128 As they do have prototypes for d3d11 functions */
129 typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
132 /* TODO: Move to a direct3d11_shaders header */
133 static const char* globVertexShaderDefault = "\
136 float4 Position : POSITION;\
137 float2 Texture : TEXCOORD0;\
142 float4 Position : SV_POSITION;\
143 float2 Texture : TEXCOORD0;\
146 VS_OUTPUT VS( VS_INPUT In )\
149 Output.Position = float4(In.Position.xy, 0.0f, 1.0f);\
150 Output.Texture = In.Texture;\
155 static const char* globPixelShaderDefault = "\
156 Texture2D shaderTexture;\
157 SamplerState SampleType;\
161 float4 Position : SV_POSITION;\
162 float2 Texture : TEXCOORD0;\
165 float4 PS( PS_INPUT In ) : SV_TARGET\
167 return shaderTexture.Sample(SampleType, In.Texture);\
171 static const char* globPixelShaderBiplanarYUV2RGB = "\
172 Texture2D shaderTextureY;\
173 Texture2D shaderTextureUV;\
174 SamplerState SampleType;\
178 float4 Position : SV_POSITION;\
179 float2 Texture : TEXCOORD0;\
182 float4 PS( PS_INPUT In ) : SV_TARGET\
186 yuv.x = shaderTextureY.Sample(SampleType, In.Texture).x;\
187 yuv.yz = shaderTextureUV.Sample(SampleType, In.Texture).xy;\
188 yuv.x = 1.164 * (yuv.x-0.0625);\
189 yuv.y = yuv.y - 0.5;\
190 yuv.z = yuv.z - 0.5;\
191 rgba.x = saturate(yuv.x + 1.596 * yuv.z);\
192 rgba.y = saturate(yuv.x - 0.813 * yuv.z - 0.391 * yuv.y);\
193 rgba.z = saturate(yuv.x + 2.018 * yuv.y);\
200 static int Open(vlc_object_t *object)
202 vout_display_t *vd = (vout_display_t *)object;
204 #if !VLC_WINSTORE_APP
205 HINSTANCE hd3d11_dll = LoadLibrary(TEXT("D3D11.DLL"));
207 msg_Warn(vd, "cannot load d3d11.dll, aborting");
211 HINSTANCE hd3dcompiler_dll = Direct3D11LoadShaderLibrary();
212 if (!hd3dcompiler_dll) {
213 msg_Err(vd, "cannot load d3dcompiler.dll, aborting");
214 FreeLibrary(hd3d11_dll);
219 HINSTANCE hdxgi_dll = LoadLibrary(TEXT("DXGI.DLL"));
221 msg_Warn(vd, "cannot load dxgi.dll, aborting");
227 IDXGISwapChain1* dxgiswapChain = var_InheritInteger(vd, "winrt-dxgiswapchain");
230 ID3D11Device* d3ddevice = var_InheritInteger(vd, "winrt-d3ddevice");
233 ID3D11DeviceContext* d3dcontext = var_InheritInteger(vd, "winrt-d3dcontext");
238 vout_display_sys_t *sys = vd->sys = calloc(1, sizeof(vout_display_sys_t));
242 #if !VLC_WINSTORE_APP
243 sys->hd3d11_dll = hd3d11_dll;
244 sys->hd3dcompiler_dll = hd3dcompiler_dll;
246 sys->OurD3DCompile = (void *)GetProcAddress(sys->hd3dcompiler_dll, "D3DCompile");
247 if (!sys->OurD3DCompile) {
248 msg_Err(vd, "Cannot locate reference to D3DCompile in d3dcompiler DLL");
249 Direct3D11Destroy(vd);
254 sys->hdxgi_dll = hdxgi_dll;
256 /* TODO : enable all dxgi versions from 1.3 -> 1.1 */
257 PFN_CREATE_DXGI_FACTORY OurCreateDXGIFactory =
258 (void *)GetProcAddress(sys->hdxgi_dll, "CreateDXGIFactory");
259 if (!OurCreateDXGIFactory) {
260 msg_Err(vd, "Cannot locate reference to CreateDXGIFactory in dxgi DLL");
261 Direct3D11Destroy(vd);
265 /* TODO : detect the directx version supported and use IID_IDXGIFactory3 or 2 */
266 HRESULT hr = OurCreateDXGIFactory(&IID_IDXGIFactory, (void **)&sys->dxgifactory);
268 msg_Err(vd, "Could not create dxgi factory. (hr=0x%lX)", hr);
269 Direct3D11Destroy(vd);
273 sys->OurD3D11CreateDeviceAndSwapChain =
274 (void *)GetProcAddress(sys->hd3d11_dll, "D3D11CreateDeviceAndSwapChain");
275 if (!sys->OurD3D11CreateDeviceAndSwapChain) {
276 msg_Err(vd, "Cannot locate reference to D3D11CreateDeviceAndSwapChain in d3d11 DLL");
277 Direct3D11Destroy(vd);
282 sys->OurD3D11CreateDevice =
283 (void *)GetProcAddress(sys->hd3d11_dll, "D3D11CreateDevice");
284 if (!sys->OurD3D11CreateDevice) {
285 msg_Err(vd, "Cannot locate reference to D3D11CreateDevice in d3d11 DLL");
286 Direct3D11Destroy(vd);
292 sys->dxgiswapChain = dxgiswapChain;
293 sys->d3ddevice = d3ddevice;
294 sys->d3dcontext = d3dcontext;
301 if (Direct3D11Open(vd, &fmt)) {
302 msg_Err(vd, "Direct3D11 could not be opened");
306 vout_display_info_t info = vd->info;
308 info.has_double_click = true;
309 info.has_hide_mouse = false;
310 info.has_pictures_invalid = true;
311 info.has_event_thread = true;
313 /* TODO : subtitle support */
314 info.subpicture_chromas = NULL;
316 video_format_Clean(&vd->fmt);
317 video_format_Copy(&vd->fmt, &fmt);
320 vd->pool = CommonPool;
321 vd->prepare = Prepare;
322 vd->display = Display;
323 vd->control = CommonControl;
324 vd->manage = CommonManage;
326 msg_Dbg(vd, "Direct3D11 Open Succeeded");
332 Direct3D11Destroy(vd);
337 static void Close(vlc_object_t *object)
339 vout_display_t * vd = (vout_display_t *)object;
343 Direct3D11Destroy(vd);
347 static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
349 vout_display_sys_t *sys = vd->sys;
350 VLC_UNUSED(subpicture);
353 /* float ClearColor[4] = { 1.0f, 0.125f, 0.3f, 1.0f }; */
354 /* ID3D11DeviceContext_ClearRenderTargetView(sys->d3dcontext,sys->d3drenderTargetView, ClearColor); */
355 ID3D11DeviceContext_ClearDepthStencilView(sys->d3dcontext,sys->d3ddepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
357 /* Render the quad */
358 ID3D11DeviceContext_VSSetShader(sys->d3dcontext, sys->d3dvertexShader, NULL, 0);
359 ID3D11DeviceContext_PSSetShader(sys->d3dcontext, sys->d3dpixelShader, NULL, 0);
360 ID3D11DeviceContext_PSSetShaderResources(sys->d3dcontext, 0, 1, &sys->d3dresViewY);
362 if( sys->d3dFormatUV )
363 ID3D11DeviceContext_PSSetShaderResources(sys->d3dcontext, 1, 1, &sys->d3dresViewUV);
365 ID3D11DeviceContext_PSSetSamplers(sys->d3dcontext, 0, 1, &sys->d3dsampState);
366 ID3D11DeviceContext_DrawIndexed(sys->d3dcontext, 6, 0, 0);
369 static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
371 vout_display_sys_t *sys = vd->sys;
373 IDXGISwapChain_Present(sys->dxgiswapChain, 0, 0);
375 picture_Release(picture);
377 subpicture_Delete(subpicture);
382 static void Direct3D11Destroy(vout_display_t *vd)
385 #if !VLC_WINSTORE_APP
387 vout_display_sys_t *sys = vd->sys;
391 FreeLibrary(sys->hdxgi_dll);
395 FreeLibrary(sys->hd3d11_dll);
396 if (sys->hd3dcompiler_dll)
397 FreeLibrary(sys->hd3dcompiler_dll);
399 /* TODO : add release of d3d11 objects here */
401 sys->OurD3D11CreateDevice = NULL;
402 sys->OurD3D11CreateDeviceAndSwapChain = NULL;
403 sys->OurD3DCompile = NULL;
404 sys->hdxgi_dll = NULL;
405 sys->hd3d11_dll = NULL;
406 sys->hd3dcompiler_dll = NULL;
414 #if !VLC_WINSTORE_APP
415 static HINSTANCE Direct3D11LoadShaderLibrary(void)
417 HINSTANCE instance = NULL;
418 /* d3dcompiler_47 is the latest on windows 8.1 */
419 for (int i = 47; i > 41; --i) {
421 _sntprintf(filename, 19, TEXT("D3DCOMPILER_%d.dll"), i);
422 instance = LoadLibrary(filename);
430 static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
432 vout_display_sys_t *sys = vd->sys;
435 #if !VLC_WINSTORE_APP
437 UINT creationFlags = 0;
440 static const D3D_FEATURE_LEVEL featureLevels[] =
442 D3D_FEATURE_LEVEL_11_1,
443 D3D_FEATURE_LEVEL_11_0,
444 D3D_FEATURE_LEVEL_10_1,
445 D3D_FEATURE_LEVEL_10_0,
446 D3D_FEATURE_LEVEL_9_3,
447 D3D_FEATURE_LEVEL_9_2,
448 D3D_FEATURE_LEVEL_9_1
451 # if !defined(NDEBUG) && defined(_MSC_VER)
452 creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
455 DXGI_SWAP_CHAIN_DESC scd;
456 memset(&scd, 0, sizeof(scd));
458 scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
459 scd.SampleDesc.Count = 1;
460 scd.SampleDesc.Quality = 0;
461 scd.BufferDesc.Width = fmt->i_visible_width;
462 scd.BufferDesc.Height = fmt->i_visible_height;
463 scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
465 # if VLC_WINSTORE_APP
466 /* TODO : check different values for performance */
467 scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
469 scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
470 scd.Flags = DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER;
471 scd.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
472 scd.Scaling = DXGI_SCALING_NONE;
475 scd.OutputWindow = sys->hvideownd;
480 /* TODO : list adapters for the user to choose from */
481 hr = IDXGIFactory_EnumAdapters(sys->dxgifactory, 0, &sys->dxgiadapter);
483 msg_Err(vd, "Could not create find factory. (hr=0x%lX)", hr);
488 hr = IDXGIAdapter_EnumOutputs(sys->dxgiadapter, 0, &output);
490 msg_Err(vd, "Could not Enumerate DXGI Outputs. (hr=0x%lX)", hr);
495 memset(&md, 0, sizeof(md));
496 md.Width = fmt->i_visible_width;
497 md.Height = fmt->i_visible_height;
498 md.Format = scd.BufferDesc.Format;
499 md.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
501 hr = IDXGIOutput_FindClosestMatchingMode(output, &md, &scd.BufferDesc, NULL);
503 msg_Err(vd, "Failed to find a supported video mode. (hr=0x%lX)", hr);
507 /* mode desc doesn't carry over the width and height*/
508 scd.BufferDesc.Width = fmt->i_visible_width;
509 scd.BufferDesc.Height = fmt->i_visible_height;
511 hr = D3D11CreateDeviceAndSwapChain(sys->dxgiadapter,
512 D3D_DRIVER_TYPE_UNKNOWN, NULL, creationFlags,
513 featureLevels, ARRAYSIZE(featureLevels),
514 D3D11_SDK_VERSION, &scd, &sys->dxgiswapChain,
515 &sys->d3ddevice, &sys->d3dfeaturelevel, &sys->d3dcontext);
517 msg_Err(vd, "Could not Create the D3D11 device and SwapChain. (hr=0x%lX)", hr);
523 static const D3D_DRIVER_TYPE driverAttempts[] = {
524 D3D_DRIVER_TYPE_HARDWARE,
525 D3D_DRIVER_TYPE_WARP,
526 D3D_DRIVER_TYPE_REFERENCE,
529 for (UINT driver = 0; driver < ARRAYSIZE(driverAttempts); driver++) {
530 hr = D3D11CreateDevice(NULL, driverAttempts[driver], NULL, creationFlags,
531 featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION,
532 &sys->d3ddevice, &sys->d3dfeaturelevel, &sys->d3dcontext);
533 if (SUCCEEDED(hr)) break;
537 msg_Err(vd, "Could not Create the D3D11 device. (hr=0x%lX)", hr);
541 IDXGIDevice *pDXGIDevice = NULL;
542 hr = ID3D11Device_QueryInterface(sys->d3ddevice, &IID_IDXGIDevice, (void **)&pDXGIDevice);
544 msg_Err(vd, "Could not Query DXGI Interface. (hr=0x%lX)", hr);
548 hr = IDXGIDevice_GetAdapter(pDXGIDevice, &sys->dxgiadapter);
550 msg_Err(vd, "Could not get the DXGI Adapter. (hr=0x%lX)", hr);
554 hr = IDXGIAdapter_GetParent(sys->dxgiadapter, &IID_IDXGIFactory, (void **)&sys->dxgifactory);
556 msg_Err(vd, "Could not get the DXGI Factory. (hr=0x%lX)", hr);
560 hr = IDXGIFactory_CreateSwapChain(sys->dxgifactory, (IUnknown *)sys->d3ddevice, &scd, &sys->dxgiswapChain);
563 msg_Err(vd, "Could not create the SwapChain. (hr=0x%lX)", hr);
567 # if VLC_WINSTORE_APP /* avoided until we can pass ISwapchainPanel without c++/cx mode */
568 /* TODO: figure out how to get "ISwapChainPanel ^panel" into brokenpanel in gcc */
569 ISwapChainPanel *brokenpanel;
570 ISwapChainPanelNative *panelNative;
571 hr = ISwapChainPanelNative_QueryInterface(brokenpanel, &IID_ISwapChainPanelNative, (void **)&pDXGIDevice);
573 msg_Err(vd, "Could not get the Native Panel. (hr=0x%lX)", hr);
577 hr = ISwapChainPanelNative_SetSwapChain(panelNative, sys->dxgiswapChain);
579 msg_Err(vd, "Could not link the SwapChain with the Native Panel. (hr=0x%lX)", hr);
587 for (unsigned i = 0; d3d_formats[i].name != 0; i++)
589 UINT i_formatSupport;
590 if( SUCCEEDED( ID3D11Device_CheckFormatSupport(sys->d3ddevice,
591 d3d_formats[i].formatTexture,
592 &i_formatSupport)) &&
593 ( i_formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D ))
595 msg_Dbg(vd, "Using pixel format %s", d3d_formats[i].name );
596 sys->d3dFormatTex = d3d_formats[i].formatTexture;
597 sys->vlcFormat = d3d_formats[i].fourcc;
598 sys->d3dFormatY = d3d_formats[i].formatY;
599 sys->d3dFormatUV = d3d_formats[i].formatUV;
603 if ( !sys->vlcFormat ) {
604 msg_Err(vd, "Could not get a suitable texture pixel format");
608 UpdateRects(vd, NULL, NULL, true);
610 if (Direct3D11CreateResources(vd, fmt)) {
611 msg_Err(vd, "Failed to allocate resources");
612 Direct3D11DestroyResources(vd);
616 EventThreadUpdateTitle(sys->event, VOUT_TITLE " (Direct3D11 output)");
618 msg_Dbg(vd, "Direct3D11 device adapter successfully initialized");
622 static void Direct3D11Close(vout_display_t *vd)
624 vout_display_sys_t *sys = vd->sys;
626 Direct3D11DestroyResources(vd);
627 if ( sys->d3dcontext )
628 ID3D11DeviceContext_Release(sys->d3dcontext);
629 if ( sys->d3ddevice )
630 ID3D11Device_Release(sys->d3ddevice);
631 msg_Dbg(vd, "Direct3D11 device adapter closed");
634 /* TODO : handle errors better
635 TODO : seperate out into smaller functions like createshaders */
636 static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
638 vout_display_sys_t *sys = vd->sys;
639 ID3D11Texture2D* pBackBuffer = NULL;
640 ID3D11Texture2D* pDepthStencil= NULL;
643 fmt->i_chroma = sys->vlcFormat;
645 hr = IDXGISwapChain_GetBuffer(sys->dxgiswapChain, 0, &IID_ID3D11Texture2D, (LPVOID *)&pBackBuffer);
647 msg_Err(vd, "Could not get the backbuffer from the Swapchain. (hr=0x%lX)", hr);
651 hr = ID3D11Device_CreateRenderTargetView(sys->d3ddevice, (ID3D11Resource *)pBackBuffer, NULL, &sys->d3drenderTargetView);
653 ID3D11Texture2D_Release(pBackBuffer);
656 msg_Err(vd, "Could not create the render view target. (hr=0x%lX)", hr);
660 D3D11_TEXTURE2D_DESC deptTexDesc;
661 memset(&deptTexDesc, 0,sizeof(deptTexDesc));
662 deptTexDesc.ArraySize = 1;
663 deptTexDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
664 deptTexDesc.CPUAccessFlags = 0;
665 deptTexDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
666 deptTexDesc.Width = fmt->i_visible_width;
667 deptTexDesc.Height = fmt->i_visible_height;
668 deptTexDesc.MipLevels = 1;
669 deptTexDesc.MiscFlags = 0;
670 deptTexDesc.SampleDesc.Count = 1;
671 deptTexDesc.SampleDesc.Quality = 0;
672 deptTexDesc.Usage = D3D11_USAGE_DEFAULT;
674 hr = ID3D11Device_CreateTexture2D(sys->d3ddevice, &deptTexDesc, NULL, &pDepthStencil);
677 msg_Err(vd, "Could not create the depth stencil texture. (hr=0x%lX)", hr);
681 D3D11_DEPTH_STENCIL_VIEW_DESC depthViewDesc;
682 memset(&depthViewDesc, 0, sizeof(depthViewDesc));
684 depthViewDesc.Format = deptTexDesc.Format;
685 depthViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
686 depthViewDesc.Texture2D.MipSlice = 0;
688 hr = ID3D11Device_CreateDepthStencilView(sys->d3ddevice, (ID3D11Resource *)pDepthStencil, &depthViewDesc, &sys->d3ddepthStencilView);
690 ID3D11Texture2D_Release(pDepthStencil);
693 msg_Err(vd, "Could not create the depth stencil view. (hr=0x%lX)", hr);
697 ID3D11DeviceContext_OMSetRenderTargets(sys->d3dcontext, 1, &sys->d3drenderTargetView, sys->d3ddepthStencilView);
700 vp.Width = (FLOAT)fmt->i_visible_width;
701 vp.Height = (FLOAT)fmt->i_visible_height;
707 ID3D11DeviceContext_RSSetViewports(sys->d3dcontext, 1, &vp);
709 ID3DBlob* pVSBlob = NULL;
711 /* TODO : Match the version to the D3D_FEATURE_LEVEL */
712 hr = D3DCompile(globVertexShaderDefault, strlen(globVertexShaderDefault),
713 NULL, NULL, NULL, "VS", "vs_4_0_level_9_1", 0, 0, &pVSBlob, NULL);
716 msg_Err(vd, "The Vertex Shader is invalid.");
720 hr = ID3D11Device_CreateVertexShader(sys->d3ddevice, (void *)ID3D10Blob_GetBufferPointer(pVSBlob),
721 ID3D10Blob_GetBufferSize(pVSBlob), NULL, &sys->d3dvertexShader);
724 ID3D11Device_Release(pVSBlob);
725 msg_Err(vd, "Failed to create the vertex shader.");
729 D3D11_INPUT_ELEMENT_DESC layout[] = {
730 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
731 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
734 ID3D11InputLayout* pVertexLayout = NULL;
735 hr = ID3D11Device_CreateInputLayout(sys->d3ddevice, layout, 2, (void *)ID3D10Blob_GetBufferPointer(pVSBlob),
736 ID3D10Blob_GetBufferSize(pVSBlob), &pVertexLayout);
738 ID3D10Blob_Release(pVSBlob);
741 msg_Err(vd, "Failed to create the vertex input layout");
745 ID3D11DeviceContext_IASetInputLayout(sys->d3dcontext, pVertexLayout);
747 ID3DBlob* pPSBlob = NULL;
749 /* TODO : Match the version to the D3D_FEATURE_LEVEL */
750 if( sys->d3dFormatUV )
751 hr = D3DCompile(globPixelShaderBiplanarYUV2RGB, strlen(globPixelShaderBiplanarYUV2RGB),
752 NULL, NULL, NULL, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob, NULL);
754 hr = D3DCompile(globPixelShaderDefault, strlen(globPixelShaderDefault),
755 NULL, NULL, NULL, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob, NULL);
759 msg_Err(vd, "The Pixel Shader is invalid.");
763 hr = ID3D11Device_CreatePixelShader(sys->d3ddevice, (void *)ID3D10Blob_GetBufferPointer(pPSBlob),
764 ID3D10Blob_GetBufferSize(pPSBlob), NULL, &sys->d3dpixelShader);
766 ID3D10Blob_Release(pPSBlob);
769 msg_Err(vd, "Failed to create the pixel shader.");
774 -1.0f, -1.0f, -1.0f, 0.0f, 1.0f,
775 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
776 1.0f, 1.0f, -1.0f, 1.0f, 0.0f,
777 -1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
780 D3D11_BUFFER_DESC bd;
781 memset(&bd, 0, sizeof(bd));
782 bd.Usage = D3D11_USAGE_DEFAULT;
783 bd.ByteWidth = sizeof(float) * 5 * 4;
784 bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
785 bd.CPUAccessFlags = 0;
787 D3D11_SUBRESOURCE_DATA InitData;
788 memset(&InitData, 0, sizeof(InitData));
789 InitData.pSysMem = vertices;
791 ID3D11Buffer* pVertexBuffer = NULL;
792 hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, &InitData, &pVertexBuffer);
795 msg_Err(vd, "Failed to create vertex buffer.");
799 UINT stride = sizeof(float) * 5;
801 ID3D11DeviceContext_IASetVertexBuffers(sys->d3dcontext, 0, 1, &pVertexBuffer, &stride, &offset);
803 ID3D11Buffer_Release(pVertexBuffer);
810 bd.Usage = D3D11_USAGE_DEFAULT;
811 bd.ByteWidth = sizeof(WORD)*6;
812 bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
813 bd.CPUAccessFlags = 0;
814 InitData.pSysMem = indices;
816 ID3D11Buffer* pIndexBuffer = NULL;
817 hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, &InitData, &pIndexBuffer);
819 msg_Err(vd, "Failed to create index buffer.");
823 ID3D11DeviceContext_IASetIndexBuffer(sys->d3dcontext, pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
825 ID3D11Buffer_Release(pVertexBuffer);
827 ID3D11DeviceContext_IASetPrimitiveTopology(sys->d3dcontext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
829 D3D11_TEXTURE2D_DESC texDesc;
830 memset(&texDesc, 0, sizeof(texDesc));
831 texDesc.Width = fmt->i_visible_width;
832 texDesc.Height = fmt->i_visible_height;
833 texDesc.MipLevels = texDesc.ArraySize = 1;
834 texDesc.Format = sys->d3dFormatTex;
835 texDesc.SampleDesc.Count = 1;
836 texDesc.Usage = D3D11_USAGE_DYNAMIC;
837 texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
838 texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
839 texDesc.MiscFlags = 0;
841 hr = ID3D11Device_CreateTexture2D(sys->d3ddevice, &texDesc, NULL, &sys->d3dtexture);
843 msg_Err(vd, "Could not Create the D3d11 Texture. (hr=0x%lX)", hr);
847 D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc;
848 memset(&resviewDesc, 0, sizeof(resviewDesc));
849 resviewDesc.Format = sys->d3dFormatY;
850 resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
851 resviewDesc.Texture2D.MipLevels = texDesc.MipLevels;
853 hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, (ID3D11Resource *)sys->d3dtexture, &resviewDesc, &sys->d3dresViewY);
855 if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
856 msg_Err(vd, "Could not Create the Y D3d11 Texture ResourceView. (hr=0x%lX)", hr);
860 if( sys->d3dFormatUV )
862 resviewDesc.Format = sys->d3dFormatUV;
863 hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, (ID3D11Resource *)sys->d3dtexture, &resviewDesc, &sys->d3dresViewUV);
865 if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
866 msg_Err(vd, "Could not Create the UV D3d11 Texture ResourceView. (hr=0x%lX)", hr);
871 D3D11_SAMPLER_DESC sampDesc;
872 memset(&sampDesc, 0, sizeof(sampDesc));
873 sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
874 sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
875 sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
876 sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
877 sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
879 sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
881 hr = ID3D11Device_CreateSamplerState(sys->d3ddevice, &sampDesc, &sys->d3dsampState);
884 if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
885 msg_Err(vd, "Could not Create the D3d11 Sampler State. (hr=0x%lX)", hr);
889 picture_sys_t *picsys = malloc(sizeof(*picsys));
890 if (unlikely(picsys == NULL)) {
891 if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
895 picsys->texture = sys->d3dtexture;
896 picsys->context = sys->d3dcontext;
899 picture_resource_t resource = { .p_sys = picsys };
900 for (int i = 0; i < PICTURE_PLANE_MAX; i++)
901 resource.p[i].i_lines = fmt->i_visible_height / (i > 0 ? 2 : 1);
903 picture_t *picture = picture_NewFromResource(fmt, &resource);
905 if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
909 sys->picsys = picsys;
911 picture_pool_configuration_t pool_cfg;
912 memset(&pool_cfg, 0, sizeof(pool_cfg));
913 pool_cfg.picture_count = 1;
914 pool_cfg.picture = &picture;
915 pool_cfg.lock = Direct3D11MapTexture;
917 sys->pool = picture_pool_NewExtended(&pool_cfg);
919 picture_Release(picture);
920 if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
924 msg_Dbg(vd, "Direct3D11 resources created");
928 static void Direct3D11DestroyResources(vout_display_t *vd)
930 vout_display_sys_t *sys = vd->sys;
932 /* TODO: Destroy Shaders? */
934 picture_sys_t *picsys = sys->picsys;
935 ID3D11Texture2D_Release(picsys->texture);
936 picture_pool_Release(sys->pool);
940 msg_Dbg(vd, "Direct3D11 resources destroyed");
943 static int Direct3D11MapTexture(picture_t *picture)
945 D3D11_MAPPED_SUBRESOURCE mappedResource;
948 hr = ID3D11DeviceContext_Map(picture->p_sys->context, (ID3D11Resource *)picture->p_sys->texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
951 msg_Dbg( picture->p_sys->vd, "failed to map the texture (hr=0x%lX)", hr );
954 res = CommonUpdatePicture(picture, NULL, mappedResource.pData, mappedResource.RowPitch);
955 ID3D11DeviceContext_Unmap(picture->p_sys->context,(ID3D11Resource *)picture->p_sys->texture, 0);