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 #include "dxgi_fmt.h"
30 
31 typedef struct
32 {
33     const char   *name;
34     DXGI_FORMAT  format;
35     vlc_fourcc_t vlc_format;
36 } dxgi_format_t;
37 
38 static const dxgi_format_t dxgi_formats[] = {
39     { "NV12",        DXGI_FORMAT_NV12,                VLC_CODEC_NV12     },
40     { "I420_OPAQUE", DXGI_FORMAT_420_OPAQUE,          0                  },
41     { "RGBA",        DXGI_FORMAT_R8G8B8A8_UNORM,      VLC_CODEC_RGBA     },
42     { "RGBA_SRGB",   DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, VLC_CODEC_RGBA     },
43     { "BGRX",        DXGI_FORMAT_B8G8R8X8_UNORM,      VLC_CODEC_RGB32    },
44     { "BGRA",        DXGI_FORMAT_B8G8R8A8_UNORM,      VLC_CODEC_BGRA     },
45     { "BGRA_SRGB",   DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, VLC_CODEC_BGRA     },
46     { "AYUV",        DXGI_FORMAT_AYUV,                VLC_CODEC_YUVA     },
47     { "YUY2",        DXGI_FORMAT_YUY2,                VLC_CODEC_YUYV     },
48     { "AI44",        DXGI_FORMAT_AI44,                0                  },
49     { "P8",          DXGI_FORMAT_P8,                  0                  },
50     { "A8P8",        DXGI_FORMAT_A8P8,                0                  },
51     { "B5G6R5",      DXGI_FORMAT_B5G6R5_UNORM,        VLC_CODEC_RGB16    },
52     { "Y416",        DXGI_FORMAT_Y416,                0                  },
53     { "P010",        DXGI_FORMAT_P010,                VLC_CODEC_P010     },
54     { "P016",        DXGI_FORMAT_P016,                0                  },
55     { "Y210",        DXGI_FORMAT_Y210,                VLC_CODEC_YUYV     }, /* AV_PIX_FMT_YUYV422 */
56     { "Y410",        DXGI_FORMAT_Y410,                0                  },
57     { "NV11",        DXGI_FORMAT_NV11,                0                  },
58     { "RGB10A2",     DXGI_FORMAT_R10G10B10A2_UNORM,   VLC_CODEC_RGBA10   },
59     { "RGB16",       DXGI_FORMAT_R16G16B16A16_UNORM,  VLC_CODEC_RGBA64   },
60     { "RGB16_FLOAT", DXGI_FORMAT_R16G16B16A16_FLOAT,  0                  },
61     { "UNKNOWN",     DXGI_FORMAT_UNKNOWN,             0                  },
62 
63     { NULL, 0, 0}
64 };
65 
66 static const d3d_format_t d3d_formats[] = {
67     { "NV12",     DXGI_FORMAT_NV12,           VLC_CODEC_NV12,              8, 2, 2, { DXGI_FORMAT_R8_UNORM,       DXGI_FORMAT_R8G8_UNORM } },
68     { "VA_NV12",  DXGI_FORMAT_NV12,           VLC_CODEC_D3D11_OPAQUE,      8, 2, 2, { DXGI_FORMAT_R8_UNORM,       DXGI_FORMAT_R8G8_UNORM } },
69     { "P010",     DXGI_FORMAT_P010,           VLC_CODEC_P010,             10, 2, 2, { DXGI_FORMAT_R16_UNORM,      DXGI_FORMAT_R16G16_UNORM } },
70     { "VA_P010",  DXGI_FORMAT_P010,           VLC_CODEC_D3D11_OPAQUE_10B, 10, 2, 2, { DXGI_FORMAT_R16_UNORM,      DXGI_FORMAT_R16G16_UNORM } },
71     { "YUY2",     DXGI_FORMAT_YUY2,           VLC_CODEC_YUYV,              8, 2, 2, { DXGI_FORMAT_R8G8B8A8_UNORM } },
72 #ifdef BROKEN_PIXEL
73     { "Y416",     DXGI_FORMAT_Y416,           VLC_CODEC_I444_16L,     16, 1, 1, { DXGI_FORMAT_R16G16B16A16_UINT } },
74 #endif
75 #ifdef UNTESTED
76     { "Y210",     DXGI_FORMAT_Y210,           VLC_CODEC_I422_10L,     10, 2, 1, { DXGI_FORMAT_R16G16B16A16_UNORM } },
77     { "Y410",     DXGI_FORMAT_Y410,           VLC_CODEC_I444,         10, 1, 1, { DXGI_FORMAT_R10G10B10A2_UNORM } },
78     { "NV11",     DXGI_FORMAT_NV11,           VLC_CODEC_I411,          8, 4, 1, { DXGI_FORMAT_R8_UNORM,           DXGI_FORMAT_R8G8_UNORM} },
79 #endif
80     { "I420",     DXGI_FORMAT_UNKNOWN,        VLC_CODEC_I420,          8, 2, 2, { DXGI_FORMAT_R8_UNORM,      DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM } },
81     { "I420_10",  DXGI_FORMAT_UNKNOWN,        VLC_CODEC_I420_10L,     10, 2, 2, { DXGI_FORMAT_R16_UNORM,     DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM } },
82     { "YUVA",     DXGI_FORMAT_UNKNOWN,        VLC_CODEC_YUVA,          8, 1, 1, { DXGI_FORMAT_R8_UNORM,      DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM } },
83     { "B8G8R8A8", DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_BGRA,          8, 1, 1, { DXGI_FORMAT_B8G8R8A8_UNORM } },
84     { "VA_BGRA",  DXGI_FORMAT_B8G8R8A8_UNORM, VLC_CODEC_D3D11_OPAQUE,  8, 1, 1, { DXGI_FORMAT_B8G8R8A8_UNORM } },
85     { "R8G8B8A8", DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_RGBA,          8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
86     { "VA_RGBA",  DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_D3D11_OPAQUE,  8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
87     { "R8G8B8X8", DXGI_FORMAT_B8G8R8X8_UNORM, VLC_CODEC_RGB32,         8, 1, 1, { DXGI_FORMAT_B8G8R8X8_UNORM } },
88     { "RGBA64",   DXGI_FORMAT_R16G16B16A16_UNORM, VLC_CODEC_RGBA64,   16, 1, 1, { DXGI_FORMAT_R16G16B16A16_UNORM } },
89     { "RGB10A2",  DXGI_FORMAT_R10G10B10A2_UNORM, VLC_CODEC_RGBA10,    10, 1, 1, { DXGI_FORMAT_R10G10B10A2_UNORM } },
90     { "AYUV",     DXGI_FORMAT_AYUV,           VLC_CODEC_VUYA,          8, 1, 1, { DXGI_FORMAT_R8G8B8A8_UNORM } },
91     { "B5G6R5",   DXGI_FORMAT_B5G6R5_UNORM,   VLC_CODEC_RGB16,         5, 1, 1, { DXGI_FORMAT_B5G6R5_UNORM } },
92     { "I420_OPAQUE", DXGI_FORMAT_420_OPAQUE,  VLC_CODEC_D3D11_OPAQUE,  8, 2, 2, { DXGI_FORMAT_UNKNOWN } },
93 
94     { NULL, 0, 0, 0, 0, 0, {} }
95 };
96 
DxgiFormatToStr(DXGI_FORMAT format)97 const char *DxgiFormatToStr(DXGI_FORMAT format)
98 {
99     for (const dxgi_format_t *f = dxgi_formats; f->name != NULL; ++f)
100     {
101         if (f->format == format)
102             return f->name;
103     }
104     return NULL;
105 }
106 
DxgiFormatFourcc(DXGI_FORMAT format)107 vlc_fourcc_t DxgiFormatFourcc(DXGI_FORMAT format)
108 {
109     for (const dxgi_format_t *f = dxgi_formats; f->name != NULL; ++f)
110     {
111         if (f->format == format)
112             return f->vlc_format;
113     }
114     return 0;
115 }
116 
GetRenderFormatList(void)117 const d3d_format_t *GetRenderFormatList(void)
118 {
119     return d3d_formats;
120 }
121 
DxgiFormatMask(DXGI_FORMAT format,video_format_t * fmt)122 void DxgiFormatMask(DXGI_FORMAT format, video_format_t *fmt)
123 {
124     if (format == DXGI_FORMAT_B8G8R8X8_UNORM)
125     {
126         fmt->i_rmask = 0x0000ff00;
127         fmt->i_gmask = 0x00ff0000;
128         fmt->i_bmask = 0xff000000;
129     }
130 }
131 
DxgiVendorStr(int gpu_vendor)132 const char *DxgiVendorStr(int gpu_vendor)
133 {
134     static const struct {
135         unsigned   id;
136         const char name[32];
137     } vendors [] = {
138         { GPU_MANUFACTURER_AMD,      "ATI"         },
139         { GPU_MANUFACTURER_NVIDIA,   "NVIDIA"      },
140         { GPU_MANUFACTURER_VIA,      "VIA"         },
141         { GPU_MANUFACTURER_INTEL,    "Intel"       },
142         { GPU_MANUFACTURER_S3,       "S3 Graphics" },
143         { GPU_MANUFACTURER_QUALCOMM, "Qualcomm"    },
144         { 0,                         "Unknown" }
145     };
146 
147     int i = 0;
148     for (i = 0; vendors[i].id != 0; i++) {
149         if (vendors[i].id == gpu_vendor)
150             break;
151     }
152     return vendors[i].name;
153 }
154 
DxgiResourceCount(const d3d_format_t * d3d_fmt)155 UINT DxgiResourceCount(const d3d_format_t *d3d_fmt)
156 {
157     for (UINT count=0; count<D3D11_MAX_SHADER_VIEW; count++)
158     {
159         if (d3d_fmt->resourceFormat[count] == DXGI_FORMAT_UNKNOWN)
160             return count;
161     }
162     return D3D11_MAX_SHADER_VIEW;
163 }
164