macOS vout: fix forgotten ';'
[vlc.git] / modules / video_chroma / d3d11_fmt.c
blob9247ac062880eeafbc4ae00e6252b1e2768527b6
1 /*****************************************************************************
2 * d3d11_fmt.c : D3D11 helper calls
3 *****************************************************************************
4 * Copyright © 2017 VLC authors, VideoLAN and VideoLabs
6 * Authors: Steve Lhomme <robux4@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 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <vlc_common.h>
28 #include <vlc_picture.h>
30 #define COBJMACROS
31 #include <d3d11.h>
32 #include <assert.h>
33 #if !defined(NDEBUG) && defined(HAVE_DXGIDEBUG_H)
34 # include <initguid.h>
35 # include <dxgidebug.h>
36 #endif
38 #include "d3d11_fmt.h"
40 #include "../codec/avcodec/va_surface.h"
42 picture_sys_t *ActivePictureSys(picture_t *p_pic)
44 struct va_pic_context *pic_ctx = (struct va_pic_context*)p_pic->context;
45 return pic_ctx ? &pic_ctx->picsys : p_pic->p_sys;
48 void AcquirePictureSys(picture_sys_t *p_sys)
50 for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++) {
51 if (p_sys->resourceView[i])
52 ID3D11ShaderResourceView_AddRef(p_sys->resourceView[i]);
53 if (p_sys->texture[i])
54 ID3D11Texture2D_AddRef(p_sys->texture[i]);
56 if (p_sys->context)
57 ID3D11DeviceContext_AddRef(p_sys->context);
58 if (p_sys->decoder)
59 ID3D11VideoDecoderOutputView_AddRef(p_sys->decoder);
60 if (p_sys->processorInput)
61 ID3D11VideoProcessorInputView_AddRef(p_sys->processorInput);
62 if (p_sys->processorOutput)
63 ID3D11VideoProcessorOutputView_AddRef(p_sys->processorOutput);
66 void ReleasePictureSys(picture_sys_t *p_sys)
68 for (int i=0; i<D3D11_MAX_SHADER_VIEW; i++) {
69 if (p_sys->resourceView[i])
70 ID3D11ShaderResourceView_Release(p_sys->resourceView[i]);
71 if (p_sys->texture[i])
72 ID3D11Texture2D_Release(p_sys->texture[i]);
74 if (p_sys->context)
75 ID3D11DeviceContext_Release(p_sys->context);
76 if (p_sys->decoder)
77 ID3D11VideoDecoderOutputView_Release(p_sys->decoder);
78 if (p_sys->processorInput)
79 ID3D11VideoProcessorInputView_Release(p_sys->processorInput);
80 if (p_sys->processorOutput)
81 ID3D11VideoProcessorOutputView_Release(p_sys->processorOutput);
84 /* map texture planes to resource views */
85 int AllocateShaderView(vlc_object_t *obj, ID3D11Device *d3ddevice,
86 const d3d_format_t *format,
87 ID3D11Texture2D *p_texture[D3D11_MAX_SHADER_VIEW], UINT slice_index,
88 ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW])
90 HRESULT hr;
91 int i;
92 D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc = { 0 };
93 D3D11_TEXTURE2D_DESC texDesc;
94 ID3D11Texture2D_GetDesc(p_texture[0], &texDesc);
95 assert(texDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE);
97 if (texDesc.ArraySize == 1)
99 resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
100 resviewDesc.Texture2D.MipLevels = 1;
102 else
104 resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
105 resviewDesc.Texture2DArray.MipLevels = -1;
106 resviewDesc.Texture2DArray.ArraySize = 1;
107 resviewDesc.Texture2DArray.FirstArraySlice = slice_index;
108 assert(slice_index < texDesc.ArraySize);
110 for (i=0; i<D3D11_MAX_SHADER_VIEW; i++)
112 resviewDesc.Format = format->resourceFormat[i];
113 if (resviewDesc.Format == DXGI_FORMAT_UNKNOWN)
114 resourceView[i] = NULL;
115 else
117 hr = ID3D11Device_CreateShaderResourceView(d3ddevice, (ID3D11Resource*)p_texture[i], &resviewDesc, &resourceView[i]);
118 if (FAILED(hr)) {
119 msg_Err(obj, "Could not Create the Texture ResourceView %d slice %d. (hr=0x%lX)", i, slice_index, hr);
120 break;
125 if (i != D3D11_MAX_SHADER_VIEW)
127 while (--i >= 0)
129 ID3D11ShaderResourceView_Release(resourceView[i]);
130 resourceView[i] = NULL;
132 return VLC_EGENERIC;
135 return VLC_SUCCESS;
139 #if !VLC_WINSTORE_APP
140 static HKEY GetAdapterRegistry(DXGI_ADAPTER_DESC *adapterDesc)
142 HKEY hKey;
143 TCHAR key[128];
144 TCHAR szData[256], lookup[256];
145 DWORD len = 256;
147 _sntprintf(lookup, 256, TEXT("pci\\ven_%04x&dev_%04x"), adapterDesc->VendorId, adapterDesc->DeviceId);
148 for (int i=0;;i++)
150 _sntprintf(key, 128, TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\%04d"), i);
151 if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey) != ERROR_SUCCESS )
152 return NULL;
154 len = sizeof(szData);
155 if( RegQueryValueEx( hKey, TEXT("MatchingDeviceId"), NULL, NULL, (LPBYTE) &szData, &len ) == ERROR_SUCCESS ) {
156 if (_tcsncmp(lookup, szData, _tcslen(lookup)) == 0)
157 return hKey;
160 RegCloseKey(hKey);
162 return NULL;
164 #endif
166 #undef D3D11_GetDriverVersion
167 void D3D11_GetDriverVersion(vlc_object_t *obj, d3d11_device_t *d3d_dev)
169 memset(&d3d_dev->WDDM, 0, sizeof(d3d_dev->WDDM));
171 #if VLC_WINSTORE_APP
172 return;
173 #else
174 IDXGIAdapter *pAdapter = D3D11DeviceAdapter(d3d_dev->d3ddevice);
175 if (!pAdapter)
176 return;
178 DXGI_ADAPTER_DESC adapterDesc;
179 HRESULT hr = IDXGIAdapter_GetDesc(pAdapter, &adapterDesc);
180 IDXGIAdapter_Release(pAdapter);
181 if (FAILED(hr))
182 return;
184 LONG err = ERROR_ACCESS_DENIED;
185 TCHAR szData[256];
186 DWORD len = 256;
187 HKEY hKey = GetAdapterRegistry(&adapterDesc);
188 if (hKey == NULL)
189 return;
191 err = RegQueryValueEx( hKey, TEXT("DriverVersion"), NULL, NULL, (LPBYTE) &szData, &len );
192 RegCloseKey(hKey);
194 if (err != ERROR_SUCCESS )
195 return;
197 int wddm, d3d_features, revision, build;
198 /* see https://msdn.microsoft.com/windows/hardware/commercialize/design/compatibility/device-graphics */
199 if (_stscanf(szData, TEXT("%d.%d.%d.%d"), &wddm, &d3d_features, &revision, &build) != 4)
200 return;
201 d3d_dev->WDDM.wddm = wddm;
202 d3d_dev->WDDM.d3d_features = d3d_features;
203 d3d_dev->WDDM.revision = revision;
204 d3d_dev->WDDM.build = build;
205 msg_Dbg(obj, "%s WDDM driver %d.%d.%d.%d", DxgiVendorStr(adapterDesc.VendorId), wddm, d3d_features, revision, build);
206 #endif
209 void D3D11_ReleaseDevice(d3d11_device_t *d3d_dev)
211 if (d3d_dev->d3dcontext)
213 ID3D11DeviceContext_Flush(d3d_dev->d3dcontext);
214 ID3D11DeviceContext_Release(d3d_dev->d3dcontext);
215 d3d_dev->d3dcontext = NULL;
217 if (d3d_dev->d3ddevice)
219 ID3D11Device_Release(d3d_dev->d3ddevice);
220 d3d_dev->d3ddevice = NULL;
224 #undef D3D11_CreateDevice
225 HRESULT D3D11_CreateDevice(vlc_object_t *obj, d3d11_handle_t *hd3d,
226 bool hw_decoding, d3d11_device_t *out)
228 #if !VLC_WINSTORE_APP
229 # define D3D11CreateDevice(args...) pf_CreateDevice(args)
230 /* */
231 PFN_D3D11_CREATE_DEVICE pf_CreateDevice;
232 pf_CreateDevice = (void *)GetProcAddress(hd3d->hdll, "D3D11CreateDevice");
233 if (!pf_CreateDevice) {
234 msg_Err(obj, "Cannot locate reference to D3D11CreateDevice ABI in DLL");
235 return E_NOINTERFACE;
237 #endif /* VLC_WINSTORE_APP */
239 HRESULT hr = E_NOTIMPL;
240 UINT creationFlags = 0;
242 if (hw_decoding || !obj->obj.force)
243 creationFlags |= D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
245 #if !defined(NDEBUG)
246 # if !VLC_WINSTORE_APP
247 if (IsDebuggerPresent())
248 # endif /* VLC_WINSTORE_APP */
250 HINSTANCE sdklayer_dll = LoadLibrary(TEXT("d3d11_1sdklayers.dll"));
251 if (sdklayer_dll) {
252 creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
253 FreeLibrary(sdklayer_dll);
256 #endif
258 static const D3D_DRIVER_TYPE driverAttempts[] = {
259 D3D_DRIVER_TYPE_HARDWARE,
260 #if 0 /* ifndef NDEBUG */
261 D3D_DRIVER_TYPE_REFERENCE,
262 #endif
265 static D3D_FEATURE_LEVEL D3D11_features[] = {
266 D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
267 D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0,
268 D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1
271 for (UINT driver = 0; driver < ARRAY_SIZE(driverAttempts); driver++) {
272 hr = D3D11CreateDevice(NULL, driverAttempts[driver], NULL, creationFlags,
273 D3D11_features, ARRAY_SIZE(D3D11_features), D3D11_SDK_VERSION,
274 &out->d3ddevice, &out->feature_level, &out->d3dcontext);
275 if (SUCCEEDED(hr)) {
276 #ifndef NDEBUG
277 msg_Dbg(obj, "Created the D3D11 device 0x%p ctx 0x%p type %d level %x.",
278 (void *)out->d3ddevice, (void *)out->d3dcontext,
279 driverAttempts[driver], out->feature_level);
280 D3D11_GetDriverVersion( obj, out );
281 #endif
282 /* we can work with legacy levels but only if forced */
283 if ( obj->obj.force || out->feature_level >= D3D_FEATURE_LEVEL_11_0 )
284 break;
285 msg_Dbg(obj, "Incompatible feature level %x", out->feature_level);
286 ID3D11DeviceContext_Release(out->d3dcontext);
287 ID3D11Device_Release(out->d3ddevice);
288 out->d3dcontext = NULL;
289 out->d3ddevice = NULL;
290 hr = E_NOTIMPL;
294 if (SUCCEEDED(hr))
295 out->owner = true;
297 return hr;
300 IDXGIAdapter *D3D11DeviceAdapter(ID3D11Device *d3ddev)
302 IDXGIDevice *pDXGIDevice = NULL;
303 HRESULT hr = ID3D11Device_QueryInterface(d3ddev, &IID_IDXGIDevice, (void **)&pDXGIDevice);
304 if (FAILED(hr)) {
305 return NULL;
308 IDXGIAdapter *p_adapter;
309 hr = IDXGIDevice_GetAdapter(pDXGIDevice, &p_adapter);
310 IDXGIDevice_Release(pDXGIDevice);
311 if (FAILED(hr)) {
312 return NULL;
314 return p_adapter;
317 bool isXboxHardware(ID3D11Device *d3ddev)
319 IDXGIAdapter *p_adapter = D3D11DeviceAdapter(d3ddev);
320 if (!p_adapter)
321 return NULL;
323 bool result = false;
324 DXGI_ADAPTER_DESC adapterDesc;
325 if (SUCCEEDED(IDXGIAdapter_GetDesc(p_adapter, &adapterDesc))) {
326 if (adapterDesc.VendorId == 0 &&
327 adapterDesc.DeviceId == 0 &&
328 !wcscmp(L"ROOT\\SraKmd\\0000", adapterDesc.Description))
329 result = true;
332 IDXGIAdapter_Release(p_adapter);
333 return result;
336 static bool isNvidiaHardware(ID3D11Device *d3ddev)
338 IDXGIAdapter *p_adapter = D3D11DeviceAdapter(d3ddev);
339 if (!p_adapter)
340 return false;
342 DXGI_ADAPTER_DESC adapterDesc;
343 if (FAILED(IDXGIAdapter_GetDesc(p_adapter, &adapterDesc)))
344 adapterDesc.VendorId = 0;
345 IDXGIAdapter_Release(p_adapter);
347 return adapterDesc.VendorId == GPU_MANUFACTURER_NVIDIA;
350 bool CanUseVoutPool(d3d11_device_t *d3d_dev, UINT slices)
352 #if VLC_WINSTORE_APP
353 /* Phones and the Xbox are memory constrained, rely on the d3d11va pool
354 * which is always smaller, we still get direct rendering from the decoder */
355 return false;
356 #else
357 /* NVIDIA cards crash when calling CreateVideoDecoderOutputView
358 * on more than 30 slices */
359 return slices <= 30 || !isNvidiaHardware(d3d_dev->d3ddevice);
360 #endif
363 int D3D11CheckDriverVersion(d3d11_device_t *d3d_dev, UINT vendorId, const struct wddm_version *min_ver)
365 IDXGIAdapter *pAdapter = D3D11DeviceAdapter(d3d_dev->d3ddevice);
366 if (!pAdapter)
367 return VLC_EGENERIC;
369 DXGI_ADAPTER_DESC adapterDesc;
370 HRESULT hr = IDXGIAdapter_GetDesc(pAdapter, &adapterDesc);
371 IDXGIAdapter_Release(pAdapter);
372 if (FAILED(hr))
373 return VLC_EGENERIC;
375 if (vendorId && adapterDesc.VendorId != vendorId)
376 return VLC_SUCCESS;
378 int build = d3d_dev->WDDM.build;
379 if (adapterDesc.VendorId == GPU_MANUFACTURER_INTEL && d3d_dev->WDDM.revision >= 100)
381 /* new Intel driver format */
382 build += (d3d_dev->WDDM.revision - 100) * 1000;
385 if (min_ver->wddm)
387 if (d3d_dev->WDDM.wddm > min_ver->wddm)
388 return VLC_SUCCESS;
389 else if (d3d_dev->WDDM.wddm != min_ver->wddm)
390 return VLC_EGENERIC;
392 if (min_ver->d3d_features)
394 if (d3d_dev->WDDM.d3d_features > min_ver->d3d_features)
395 return VLC_SUCCESS;
396 else if (d3d_dev->WDDM.d3d_features != min_ver->d3d_features)
397 return VLC_EGENERIC;
399 if (min_ver->revision)
401 if (d3d_dev->WDDM.revision > min_ver->revision)
402 return VLC_SUCCESS;
403 else if (d3d_dev->WDDM.revision != min_ver->revision)
404 return VLC_EGENERIC;
406 if (min_ver->build)
408 if (build > min_ver->build)
409 return VLC_SUCCESS;
410 else if (build != min_ver->build)
411 return VLC_EGENERIC;
413 return VLC_SUCCESS;
416 const d3d_format_t *FindD3D11Format(ID3D11Device *d3ddevice,
417 vlc_fourcc_t i_src_chroma,
418 bool rgb_only,
419 uint8_t bits_per_channel,
420 bool allow_opaque,
421 UINT supportFlags)
423 supportFlags |= D3D11_FORMAT_SUPPORT_TEXTURE2D;
424 for (const d3d_format_t *output_format = GetRenderFormatList();
425 output_format->name != NULL; ++output_format)
427 if (i_src_chroma && i_src_chroma != output_format->fourcc)
428 continue;
429 if (bits_per_channel && bits_per_channel > output_format->bitsPerChannel)
430 continue;
431 if (!allow_opaque && is_d3d11_opaque(output_format->fourcc))
432 continue;
433 if (rgb_only && vlc_fourcc_IsYUV(output_format->fourcc))
434 continue;
436 DXGI_FORMAT textureFormat;
437 if (output_format->formatTexture == DXGI_FORMAT_UNKNOWN)
438 textureFormat = output_format->resourceFormat[0];
439 else
440 textureFormat = output_format->formatTexture;
442 if( DeviceSupportsFormat( d3ddevice, textureFormat, supportFlags ) )
443 return output_format;
445 return NULL;
448 int AllocateTextures( vlc_object_t *obj, d3d11_device_t *d3d_dev,
449 const d3d_format_t *cfg, const video_format_t *fmt,
450 unsigned pool_size, ID3D11Texture2D *textures[] )
452 plane_t planes[PICTURE_PLANE_MAX];
453 int plane, plane_count;
454 HRESULT hr;
455 ID3D11Texture2D *slicedTexture = NULL;
456 D3D11_TEXTURE2D_DESC texDesc;
457 ZeroMemory(&texDesc, sizeof(texDesc));
458 texDesc.MipLevels = 1;
459 texDesc.SampleDesc.Count = 1;
460 texDesc.MiscFlags = 0; //D3D11_RESOURCE_MISC_SHARED;
461 texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
462 if (is_d3d11_opaque(fmt->i_chroma)) {
463 texDesc.BindFlags |= D3D11_BIND_DECODER;
464 texDesc.Usage = D3D11_USAGE_DEFAULT;
465 texDesc.CPUAccessFlags = 0;
466 } else {
467 texDesc.Usage = D3D11_USAGE_DYNAMIC;
468 texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
470 texDesc.ArraySize = pool_size;
472 const vlc_chroma_description_t *p_chroma_desc = vlc_fourcc_GetChromaDescription( fmt->i_chroma );
473 if( !p_chroma_desc )
474 return VLC_EGENERIC;
476 if (cfg->formatTexture == DXGI_FORMAT_UNKNOWN) {
477 if (p_chroma_desc->plane_count == 0)
479 msg_Dbg(obj, "failed to get the pixel format planes for %4.4s", (char *)&fmt->i_chroma);
480 return VLC_EGENERIC;
482 assert(p_chroma_desc->plane_count <= D3D11_MAX_SHADER_VIEW);
483 plane_count = p_chroma_desc->plane_count;
485 texDesc.Format = cfg->resourceFormat[0];
486 assert(cfg->resourceFormat[1] == cfg->resourceFormat[0]);
487 assert(cfg->resourceFormat[2] == cfg->resourceFormat[0]);
489 for( int i = 0; i < plane_count; i++ )
491 plane_t *p = &planes[i];
493 p->i_lines = fmt->i_height * p_chroma_desc->p[i].h.num / p_chroma_desc->p[i].h.den;
494 p->i_visible_lines = fmt->i_visible_height * p_chroma_desc->p[i].h.num / p_chroma_desc->p[i].h.den;
495 p->i_pitch = fmt->i_width * p_chroma_desc->p[i].w.num / p_chroma_desc->p[i].w.den * p_chroma_desc->pixel_size;
496 p->i_visible_pitch = fmt->i_visible_width * p_chroma_desc->p[i].w.num / p_chroma_desc->p[i].w.den * p_chroma_desc->pixel_size;
497 p->i_pixel_pitch = p_chroma_desc->pixel_size;
499 } else {
500 plane_count = 1;
501 texDesc.Format = cfg->formatTexture;
502 texDesc.Height = fmt->i_height;
503 texDesc.Width = fmt->i_width;
505 hr = ID3D11Device_CreateTexture2D( d3d_dev->d3ddevice, &texDesc, NULL, &slicedTexture );
506 if (FAILED(hr)) {
507 msg_Err(obj, "CreateTexture2D failed for the %d pool. (hr=0x%0lx)", pool_size, hr);
508 goto error;
512 for (unsigned picture_count = 0; picture_count < pool_size; picture_count++) {
513 for (plane = 0; plane < plane_count; plane++)
515 if (slicedTexture) {
516 textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = slicedTexture;
517 ID3D11Texture2D_AddRef(slicedTexture);
518 } else {
519 texDesc.Height = fmt->i_height * p_chroma_desc->p[plane].h.num / p_chroma_desc->p[plane].h.den;
520 texDesc.Width = fmt->i_width * p_chroma_desc->p[plane].w.num / p_chroma_desc->p[plane].w.den;
521 hr = ID3D11Device_CreateTexture2D( d3d_dev->d3ddevice, &texDesc, NULL, &textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] );
522 if (FAILED(hr)) {
523 msg_Err(obj, "CreateTexture2D failed for the %d pool. (hr=0x%0lx)", pool_size, hr);
524 goto error;
528 for (; plane < D3D11_MAX_SHADER_VIEW; plane++) {
529 if (!cfg->resourceFormat[plane])
530 textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = NULL;
531 else
533 textures[picture_count * D3D11_MAX_SHADER_VIEW + plane] = textures[picture_count * D3D11_MAX_SHADER_VIEW];
534 ID3D11Texture2D_AddRef(textures[picture_count * D3D11_MAX_SHADER_VIEW + plane]);
539 if (!is_d3d11_opaque(fmt->i_chroma) && cfg->formatTexture != DXGI_FORMAT_UNKNOWN) {
540 D3D11_MAPPED_SUBRESOURCE mappedResource;
541 hr = ID3D11DeviceContext_Map(d3d_dev->d3dcontext, (ID3D11Resource*)textures[0], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
542 if( FAILED(hr) ) {
543 msg_Err(obj, "The texture cannot be mapped. (hr=0x%lX)", hr);
544 goto error;
546 ID3D11DeviceContext_Unmap(d3d_dev->d3dcontext, (ID3D11Resource*)textures[0], 0);
547 if (mappedResource.RowPitch < p_chroma_desc->pixel_size * texDesc.Width) {
548 msg_Err( obj, "The texture row pitch is too small (%d instead of %d)", mappedResource.RowPitch,
549 p_chroma_desc->pixel_size * texDesc.Width );
550 goto error;
552 if ( fmt->i_width > 64 &&
553 mappedResource.RowPitch >=
554 2* (fmt->i_width * p_chroma_desc->p[0].w.num / p_chroma_desc->p[0].w.den * p_chroma_desc->pixel_size) )
556 msg_Err(obj, "Bogus %4.4s pitch detected. %d vs %d", (const char*)&fmt->i_chroma,
557 mappedResource.RowPitch,
558 (fmt->i_width * p_chroma_desc->p[0].w.num / p_chroma_desc->p[0].w.den * p_chroma_desc->pixel_size));
559 goto error;
563 if (slicedTexture)
564 ID3D11Texture2D_Release(slicedTexture);
565 return VLC_SUCCESS;
566 error:
567 if (slicedTexture)
568 ID3D11Texture2D_Release(slicedTexture);
569 return VLC_EGENERIC;
572 #undef D3D11_Create
573 int D3D11_Create(vlc_object_t *obj, d3d11_handle_t *hd3d)
575 #if !VLC_WINSTORE_APP
576 hd3d->hdll = LoadLibrary(TEXT("D3D11.DLL"));
577 if (!hd3d->hdll)
579 msg_Warn(obj, "cannot load d3d11.dll, aborting");
580 return VLC_EGENERIC;
583 # if !defined(NDEBUG) && defined(HAVE_DXGIDEBUG_H)
584 if (IsDebuggerPresent())
586 hd3d->dxgidebug_dll = LoadLibrary(TEXT("DXGIDEBUG.DLL"));
587 HRESULT (WINAPI * pf_DXGIGetDebugInterface)(const GUID *riid, void **ppDebug) = NULL;
588 if (hd3d->dxgidebug_dll)
589 pf_DXGIGetDebugInterface =
590 (void *)GetProcAddress(hd3d->dxgidebug_dll, "DXGIGetDebugInterface");
591 if (pf_DXGIGetDebugInterface) {
592 IDXGIDebug *pDXGIDebug;
593 if (SUCCEEDED(pf_DXGIGetDebugInterface(&IID_IDXGIDebug, (void**)&pDXGIDebug)))
594 IDXGIDebug_ReportLiveObjects(pDXGIDebug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
597 # endif
598 #endif
599 return VLC_SUCCESS;
602 void D3D11_Destroy(d3d11_handle_t *hd3d)
604 #if !VLC_WINSTORE_APP
605 if (hd3d->hdll)
606 FreeLibrary(hd3d->hdll);
608 #if !defined(NDEBUG) && defined(HAVE_DXGIDEBUG_H)
609 if (hd3d->dxgidebug_dll)
610 FreeLibrary(hd3d->dxgidebug_dll);
611 #endif
612 #endif
615 #ifndef NDEBUG
616 #undef D3D11_LogProcessorSupport
617 void D3D11_LogProcessorSupport(vlc_object_t *o,
618 ID3D11VideoProcessorEnumerator *processorEnumerator)
620 UINT flags;
621 HRESULT hr;
622 for (int format = 0; format < 188; format++) {
623 hr = ID3D11VideoProcessorEnumerator_CheckVideoProcessorFormat(processorEnumerator, format, &flags);
624 if (FAILED(hr))
625 continue;
626 const char *name = DxgiFormatToStr(format);
627 const char *support = NULL;
628 if ((flags & (D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT|D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT))
629 == (D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT|D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT))
630 support = "input/output";
631 else if (flags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_INPUT)
632 support = "input";
633 else if (flags & D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT)
634 support = "output";
635 if (support)
637 if (name)
638 msg_Dbg(o, "processor format %s is supported for %s", name, support);
639 else
640 msg_Dbg(o, "processor format (%d) is supported for %s", format, support);
645 #endif