d3d11_surface: avoid a cast between ID3D11Texture2D* and ID3D11Resource*
[vlc.git] / modules / video_chroma / dxgi_fmt.c
1 /*****************************************************************************
2  * dxgi_fmt.c : DXGI GPU surface conversion module for vlc
3  *****************************************************************************
4  * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
5  *
6  * Authors: Steve Lhomme <robux4@gmail.com>
7  *
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.
12  *
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.
17  *
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  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include <vlc_es.h>
28
29 #define COBJMACROS
30 #include <initguid.h>
31 #include <d3d11.h>
32
33 #include "dxgi_fmt.h"
34
35 typedef struct
36 {
37     const char   *name;
38     DXGI_FORMAT  format;
39     vlc_fourcc_t vlc_format;
40 } dxgi_format_t;
41
42 static const dxgi_format_t dxgi_formats[] = {
43     { "NV12",        DXGI_FORMAT_NV12,                VLC_CODEC_NV12     },
44     { "I420_OPAQUE", DXGI_FORMAT_420_OPAQUE,          0                  },
45     { "RGBA",        DXGI_FORMAT_R8G8B8A8_UNORM,      VLC_CODEC_RGBA     },
46     { "RGBA_SRGB",   DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, VLC_CODEC_RGBA     },
47     { "BGRX",        DXGI_FORMAT_B8G8R8X8_UNORM,      VLC_CODEC_RGB32    },
48     { "BGRA",        DXGI_FORMAT_B8G8R8A8_UNORM,      VLC_CODEC_BGRA     },
49     { "BGRA_SRGB",   DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, VLC_CODEC_BGRA     },
50     { "AYUV",        DXGI_FORMAT_AYUV,                VLC_CODEC_YUVA     },
51     { "YUY2",        DXGI_FORMAT_YUY2,                VLC_CODEC_YUYV     },
52     { "AI44",        DXGI_FORMAT_AI44,                0                  },
53     { "P8",          DXGI_FORMAT_P8,                  0                  },
54     { "A8P8",        DXGI_FORMAT_A8P8,                0                  },
55     { "B5G6R5",      DXGI_FORMAT_B5G6R5_UNORM,        VLC_CODEC_RGB16    },
56     { "Y416",        DXGI_FORMAT_Y416,                0                  },
57     { "P010",        DXGI_FORMAT_P010,                VLC_CODEC_P010     },
58     { "Y210",        DXGI_FORMAT_Y210,                VLC_CODEC_YUYV     }, /* AV_PIX_FMT_YUYV422 */
59     { "Y410",        DXGI_FORMAT_Y410,                0                  },
60     { "NV11",        DXGI_FORMAT_NV11,                0                  },
61     { "RGB10A2",     DXGI_FORMAT_R10G10B10A2_UNORM,   0                  },
62     { "RGB16_FLOAT", DXGI_FORMAT_R16G16B16A16_FLOAT,  0                  },
63     { "UNKNOWN",     DXGI_FORMAT_UNKNOWN,             0                  },
64
65     { NULL, 0, 0}
66 };
67
68 static const d3d_format_t d3d_formats[] = {
69     { "NV12",     DXGI_FORMAT_NV12,           VLC_CODEC_NV12,              8, 2, 2, { DXGI_FORMAT_R8_UNORM,       DXGI_FORMAT_R8G8_UNORM } },
70     { "VA_NV12",  DXGI_FORMAT_NV12,           VLC_CODEC_D3D11_OPAQUE,      8, 2, 2, { DXGI_FORMAT_R8_UNORM,       DXGI_FORMAT_R8G8_UNORM } },
71     { "P010",     DXGI_FORMAT_P010,           VLC_CODEC_P010,             10, 2, 2, { DXGI_FORMAT_R16_UNORM,      DXGI_FORMAT_R16G16_UNORM } },
72     { "VA_P010",  DXGI_FORMAT_P010,           VLC_CODEC_D3D11_OPAQUE_10B, 10, 2, 2, { DXGI_FORMAT_R16_UNORM,      DXGI_FORMAT_R16G16_UNORM } },
73     { "YUY2",     DXGI_FORMAT_YUY2,           VLC_CODEC_YUYV,              8, 2, 2, { DXGI_FORMAT_R8G8B8A8_UNORM } },
74 #ifdef BROKEN_PIXEL
75     { "AYUV",     DXGI_FORMAT_AYUV,           VLC_CODEC_YUVA,          8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
76     { "Y416",     DXGI_FORMAT_Y416,           VLC_CODEC_I444_16L,     16, 1, 1, { DXGI_FORMAT_R16G16B16A16_UINT } },
77 #endif
78 #ifdef UNTESTED
79     { "Y210",     DXGI_FORMAT_Y210,           VLC_CODEC_I422_10L,     10, 2, 1, { DXGI_FORMAT_R16G16B16A16_UNORM } },
80     { "Y410",     DXGI_FORMAT_Y410,           VLC_CODEC_I444,         10, 1, 1, { DXGI_FORMAT_R10G10B10A2_UNORM } },
81     { "NV11",     DXGI_FORMAT_NV11,           VLC_CODEC_I411,          8, 4, 1, { DXGI_FORMAT_R8_UNORM,           DXGI_FORMAT_R8G8_UNORM} },
82 #endif
83     { "R8G8B8A8", DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_RGBA,          8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
84     { "VA_RGBA",  DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_D3D11_OPAQUE,  8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
85     { "B8G8R8A8", DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_BGRA,          8, 1, 1, { DXGI_FORMAT_B8G8R8A8_UNORM } },
86     { "VA_BGRA",  DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_D3D11_OPAQUE,  8, 1, 1, { DXGI_FORMAT_B8G8R8A8_UNORM } },
87     { "R8G8B8X8", DXGI_FORMAT_B8G8R8X8_UNORM, VLC_CODEC_RGB32,         8, 1, 1, { DXGI_FORMAT_B8G8R8X8_UNORM } },
88     { "B5G6R5",   DXGI_FORMAT_B5G6R5_UNORM,   VLC_CODEC_RGB16,         5, 1, 1, { DXGI_FORMAT_B5G6R5_UNORM } },
89
90     { NULL, 0, 0, 0, 0, 0, {} }
91 };
92
93 const char *DxgiFormatToStr(DXGI_FORMAT format)
94 {
95     for (const dxgi_format_t *f = dxgi_formats; f->name != NULL; ++f)
96     {
97         if (f->format == format)
98             return f->name;
99     }
100     return NULL;
101 }
102
103 vlc_fourcc_t DxgiFormatFourcc(DXGI_FORMAT format)
104 {
105     for (const dxgi_format_t *f = dxgi_formats; f->name != NULL; ++f)
106     {
107         if (f->format == format)
108             return f->vlc_format;
109     }
110     return 0;
111 }
112
113 const d3d_format_t *GetRenderFormatList(void)
114 {
115     return d3d_formats;
116 }
117
118 void DxgiFormatMask(DXGI_FORMAT format, video_format_t *fmt)
119 {
120     if (format == DXGI_FORMAT_B8G8R8X8_UNORM)
121     {
122         fmt->i_rmask = 0x0000ff00;
123         fmt->i_gmask = 0x00ff0000;
124         fmt->i_bmask = 0xff000000;
125     }
126 }
127
128 IDXGIAdapter *D3D11DeviceAdapter(ID3D11Device *d3ddev)
129 {
130     IDXGIDevice *pDXGIDevice = NULL;
131     HRESULT hr = ID3D11Device_QueryInterface(d3ddev, &IID_IDXGIDevice, (void **)&pDXGIDevice);
132     if (FAILED(hr)) {
133         return NULL;
134     }
135
136     IDXGIAdapter *p_adapter;
137     hr = IDXGIDevice_GetAdapter(pDXGIDevice, &p_adapter);
138     IDXGIDevice_Release(pDXGIDevice);
139     if (FAILED(hr)) {
140         return NULL;
141     }
142     return p_adapter;
143 }
144
145 bool isXboxHardware(ID3D11Device *d3ddev)
146 {
147     IDXGIAdapter *p_adapter = D3D11DeviceAdapter(d3ddev);
148     if (!p_adapter)
149         return NULL;
150
151     bool result = false;
152     DXGI_ADAPTER_DESC adapterDesc;
153     if (SUCCEEDED(IDXGIAdapter_GetDesc(p_adapter, &adapterDesc))) {
154         if (adapterDesc.VendorId == 0 &&
155             adapterDesc.DeviceId == 0 &&
156             !wcscmp(L"ROOT\\SraKmd\\0000", adapterDesc.Description))
157             result = true;
158     }
159
160     IDXGIAdapter_Release(p_adapter);
161     return result;
162 }