1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2014-2018 - Ali Bouhlel
3 *
4 * RetroArch is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with RetroArch.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include <compat/strl.h>
17 #include <string/stdstring.h>
18 #include <retro_environment.h>
19
20 #include <assert.h>
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "dxgi_common.h"
27 #include "../../configuration.h"
28 #include "../../verbosity.h"
29 #include "../../ui/ui_companion_driver.h"
30 #include "../../retroarch.h"
31 #include "../frontend/frontend_driver.h"
32 #include "win32_common.h"
33
34 #if defined(HAVE_DYNAMIC) && !defined(__WINRT__)
35 #include <dynamic/dylib.h>
36
CreateDXGIFactory1(REFIID riid,void ** ppFactory)37 HRESULT WINAPI CreateDXGIFactory1(REFIID riid, void** ppFactory)
38 {
39 static HRESULT(WINAPI * fp)(REFIID, void**);
40
41 static dylib_t dxgi_dll;
42
43 if (!dxgi_dll)
44 dxgi_dll = dylib_load("dxgi.dll");
45
46 if (!dxgi_dll)
47 return TYPE_E_CANTLOADLIBRARY;
48
49 if (!fp)
50 fp = (HRESULT(WINAPI*)(REFIID, void**))dylib_proc(dxgi_dll, "CreateDXGIFactory1");
51
52 if (!fp)
53 return TYPE_E_DLLFUNCTIONNOTFOUND;
54
55 return fp(riid, ppFactory);
56 }
57 #endif
58
dxgi_get_format_fallback_list(DXGI_FORMAT format)59 DXGI_FORMAT* dxgi_get_format_fallback_list(DXGI_FORMAT format)
60 {
61 switch ((unsigned)format)
62 {
63 case DXGI_FORMAT_R32G32B32A32_FLOAT:
64 {
65 static DXGI_FORMAT formats[] = { DXGI_FORMAT_R32G32B32A32_FLOAT,
66 DXGI_FORMAT_R16G16B16A16_FLOAT,
67 DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT,
68 DXGI_FORMAT_UNKNOWN };
69 return formats;
70 }
71 case DXGI_FORMAT_R16G16B16A16_FLOAT:
72 {
73 static DXGI_FORMAT formats[] = { DXGI_FORMAT_R16G16B16A16_FLOAT,
74 DXGI_FORMAT_R32G32B32A32_FLOAT,
75 DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT,
76 DXGI_FORMAT_UNKNOWN };
77 return formats;
78 }
79 case DXGI_FORMAT_R8G8B8A8_UNORM:
80 {
81 static DXGI_FORMAT formats[] = { DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
82 DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_UNKNOWN };
83 return formats;
84 }
85 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
86 {
87 static DXGI_FORMAT formats[] = { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
88 DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
89 DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_UNKNOWN };
90 return formats;
91 }
92 case DXGI_FORMAT_B8G8R8A8_UNORM:
93 {
94 static DXGI_FORMAT formats[] = { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
95 DXGI_FORMAT_UNKNOWN };
96 return formats;
97 }
98 case DXGI_FORMAT_B8G8R8X8_UNORM:
99 {
100 static DXGI_FORMAT formats[] = { DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
101 DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN };
102 return formats;
103 }
104 case DXGI_FORMAT_B5G6R5_UNORM:
105 {
106 static DXGI_FORMAT formats[] = { DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM,
107 DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
108 DXGI_FORMAT_UNKNOWN };
109 return formats;
110 }
111 case DXGI_FORMAT_EX_A4R4G4B4_UNORM:
112 case DXGI_FORMAT_B4G4R4A4_UNORM:
113 {
114 static DXGI_FORMAT formats[] = { DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
115 DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN };
116 return formats;
117 }
118 case DXGI_FORMAT_A8_UNORM:
119 {
120 static DXGI_FORMAT formats[] = { DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_R8_UNORM,
121 DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
122 DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN };
123 return formats;
124 }
125 case DXGI_FORMAT_R8_UNORM:
126 {
127 static DXGI_FORMAT formats[] = { DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_A8_UNORM,
128 DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
129 DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN };
130 return formats;
131 }
132 default:
133 break;
134 }
135 return NULL;
136 }
137
138 #define FORMAT_PROCESS_( \
139 src_type, src_rb, src_gb, src_bb, src_ab, src_rs, src_gs, src_bs, src_as, dst_type, dst_rb, \
140 dst_gb, dst_bb, dst_ab, dst_rs, dst_gs, dst_bs, dst_as) \
141 do \
142 { \
143 if ((sizeof(src_type) == sizeof(dst_type)) && \
144 ((src_rs == dst_rs && src_rb == dst_rb) || !dst_rb) && \
145 ((src_gs == dst_gs && src_gb == dst_gb) || !dst_gb) && \
146 ((src_bs == dst_bs && src_bb == dst_bb) || !dst_bb) && \
147 ((src_as == dst_as && src_ab == dst_ab) || !dst_ab)) \
148 { \
149 const UINT8* in = (const UINT8*)src_data; \
150 UINT8* out = (UINT8*)dst_data; \
151 for (i = 0; i < height; i++) \
152 { \
153 memcpy(out, in, width * sizeof(src_type)); \
154 in += src_pitch ? src_pitch : width * sizeof(src_type); \
155 out += dst_pitch ? dst_pitch : width * sizeof(dst_type); \
156 } \
157 } \
158 else \
159 { \
160 const src_type* src_ptr = (const src_type*)src_data; \
161 dst_type* dst_ptr = (dst_type*)dst_data; \
162 if (src_pitch) \
163 src_pitch -= width * sizeof(*src_ptr); \
164 if (dst_pitch) \
165 dst_pitch -= width * sizeof(*dst_ptr); \
166 for (i = 0; i < height; i++) \
167 { \
168 for (j = 0; j < width; j++) \
169 { \
170 unsigned r, g, b, a; \
171 src_type src_val = *src_ptr++; \
172 if (src_rb) \
173 { \
174 r = (src_val >> src_rs) & ((1 << src_rb) - 1); \
175 r = (src_rb < dst_rb) \
176 ? (r << (dst_rb - src_rb)) | \
177 (r >> ((2 * src_rb > dst_rb) ? 2 * src_rb - dst_rb : 0)) \
178 : r >> (src_rb - dst_rb); \
179 } \
180 if (src_gb) \
181 { \
182 g = (src_val >> src_gs) & ((1 << src_gb) - 1); \
183 g = (src_gb < dst_gb) \
184 ? (g << (dst_gb - src_gb)) | \
185 (g >> ((2 * src_gb > dst_gb) ? 2 * src_gb - dst_gb : 0)) \
186 : g >> (src_gb - dst_gb); \
187 } \
188 if (src_bb) \
189 { \
190 b = (src_val >> src_bs) & ((1 << src_bb) - 1); \
191 b = (src_bb < dst_bb) \
192 ? (b << (dst_bb - src_bb)) | \
193 (b >> ((2 * src_bb > dst_bb) ? 2 * src_bb - dst_bb : 0)) \
194 : b >> (src_bb - dst_bb); \
195 } \
196 if (src_ab) \
197 { \
198 a = (src_val >> src_as) & ((1 << src_ab) - 1); \
199 a = (src_ab < dst_ab) \
200 ? (a << (dst_ab - src_ab)) | \
201 (a >> ((2 * src_ab > dst_ab) ? 2 * src_ab - dst_ab : 0)) \
202 : a >> (src_ab - dst_ab); \
203 } \
204 *dst_ptr++ = ((src_rb ? r : 0) << dst_rs) | ((src_gb ? g : 0) << dst_gs) | \
205 ((src_bb ? b : 0) << dst_bs) | \
206 ((src_ab ? a : ((1 << dst_ab) - 1)) << dst_as); \
207 } \
208 src_ptr = (src_type*)((UINT8*)src_ptr + src_pitch); \
209 dst_ptr = (dst_type*)((UINT8*)dst_ptr + dst_pitch); \
210 } \
211 } \
212 } while (0)
213
214 #define FORMAT_PROCESS(args) FORMAT_PROCESS_ args
215
216 #define FORMAT_DST(st, dt) \
217 case dt: \
218 { \
219 FORMAT_PROCESS((st##_DESCS, dt##_DESCS)); \
220 break; \
221 }
222
223 #define FORMAT_SRC(st) \
224 case st: \
225 { \
226 switch ((unsigned)dst_format) \
227 { \
228 FORMAT_DST_LIST(st); \
229 default: \
230 assert(0); \
231 break; \
232 } \
233 break; \
234 }
235
236 /* clang-format off */
237 /* r, g, b, a, r, g, b, a */
238 #define DXGI_FORMAT_R8G8B8A8_UNORM_DESCS UINT32, 8, 8, 8, 8, 0, 8, 16, 24
239 #define DXGI_FORMAT_B8G8R8X8_UNORM_DESCS UINT32, 8, 8, 8, 0, 16, 8, 0, 0
240 #define DXGI_FORMAT_B8G8R8A8_UNORM_DESCS UINT32, 8, 8, 8, 8, 16, 8, 0, 24
241 #define DXGI_FORMAT_A8_UNORM_DESCS UINT8, 0, 0, 0, 8, 0, 0, 0, 0
242 #define DXGI_FORMAT_R8_UNORM_DESCS UINT8, 8, 0, 0, 0, 0, 0, 0, 0
243 #define DXGI_FORMAT_B5G6R5_UNORM_DESCS UINT16, 5, 6, 5, 0, 11, 5, 0, 0
244 #define DXGI_FORMAT_B5G5R5A1_UNORM_DESCS UINT16, 5, 5, 5, 1, 10, 5, 0, 11
245 #define DXGI_FORMAT_B4G4R4A4_UNORM_DESCS UINT16, 4, 4, 4, 4, 8, 4, 0, 12
246 #define DXGI_FORMAT_EX_A4R4G4B4_UNORM_DESCS UINT16, 4, 4, 4, 4, 4, 8, 12, 0
247
248 #define FORMAT_SRC_LIST() \
249 FORMAT_SRC(DXGI_FORMAT_R8G8B8A8_UNORM); \
250 FORMAT_SRC(DXGI_FORMAT_B8G8R8X8_UNORM); \
251 FORMAT_SRC(DXGI_FORMAT_A8_UNORM); \
252 FORMAT_SRC(DXGI_FORMAT_R8_UNORM); \
253 FORMAT_SRC(DXGI_FORMAT_B5G6R5_UNORM); \
254 FORMAT_SRC(DXGI_FORMAT_B5G5R5A1_UNORM); \
255 FORMAT_SRC(DXGI_FORMAT_B4G4R4A4_UNORM); \
256 FORMAT_SRC(DXGI_FORMAT_B8G8R8A8_UNORM); \
257 FORMAT_SRC(DXGI_FORMAT_EX_A4R4G4B4_UNORM)
258
259 #define FORMAT_DST_LIST(srcfmt) \
260 FORMAT_DST(srcfmt, DXGI_FORMAT_R8G8B8A8_UNORM); \
261 FORMAT_DST(srcfmt, DXGI_FORMAT_B8G8R8X8_UNORM); \
262 FORMAT_DST(srcfmt, DXGI_FORMAT_A8_UNORM); \
263 FORMAT_DST(srcfmt, DXGI_FORMAT_R8_UNORM); \
264 FORMAT_DST(srcfmt, DXGI_FORMAT_B5G6R5_UNORM); \
265 FORMAT_DST(srcfmt, DXGI_FORMAT_B5G5R5A1_UNORM); \
266 FORMAT_DST(srcfmt, DXGI_FORMAT_B4G4R4A4_UNORM); \
267 FORMAT_DST(srcfmt, DXGI_FORMAT_B8G8R8A8_UNORM); \
268 FORMAT_DST(srcfmt, DXGI_FORMAT_EX_A4R4G4B4_UNORM)
269 /* clang-format on */
270
271 #ifdef _MSC_VER
272 #pragma warning(disable : 4293)
273 #endif
dxgi_copy(int width,int height,DXGI_FORMAT src_format,int src_pitch,const void * src_data,DXGI_FORMAT dst_format,int dst_pitch,void * dst_data)274 void dxgi_copy(
275 int width,
276 int height,
277 DXGI_FORMAT src_format,
278 int src_pitch,
279 const void* src_data,
280 DXGI_FORMAT dst_format,
281 int dst_pitch,
282 void* dst_data)
283 {
284 int i, j;
285
286 switch ((unsigned)src_format)
287 {
288 FORMAT_SRC_LIST();
289
290 default:
291 assert(0);
292 break;
293 }
294 }
295
296 #ifdef _MSC_VER
297 #pragma warning(default : 4293)
298 #endif
299
glslang_format_to_dxgi(glslang_format fmt)300 DXGI_FORMAT glslang_format_to_dxgi(glslang_format fmt)
301 {
302 #undef FMT_
303 #define FMT_(x) case SLANG_FORMAT_##x: return DXGI_FORMAT_##x
304 #undef FMT2
305 #define FMT2(x,y) case SLANG_FORMAT_##x: return y
306
307 switch (fmt)
308 {
309 FMT_(R8_UNORM);
310 FMT_(R8_SINT);
311 FMT_(R8_UINT);
312 FMT_(R8G8_UNORM);
313 FMT_(R8G8_SINT);
314 FMT_(R8G8_UINT);
315 FMT_(R8G8B8A8_UNORM);
316 FMT_(R8G8B8A8_SINT);
317 FMT_(R8G8B8A8_UINT);
318 FMT2(R8G8B8A8_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
319
320 FMT2(A2B10G10R10_UNORM_PACK32, DXGI_FORMAT_R10G10B10A2_UNORM);
321 FMT2(A2B10G10R10_UINT_PACK32, DXGI_FORMAT_R10G10B10A2_UNORM);
322
323 FMT_(R16_UINT);
324 FMT_(R16_SINT);
325 FMT2(R16_SFLOAT, DXGI_FORMAT_R16_FLOAT);
326 FMT_(R16G16_UINT);
327 FMT_(R16G16_SINT);
328 FMT2(R16G16_SFLOAT, DXGI_FORMAT_R16G16_FLOAT);
329 FMT_(R16G16B16A16_UINT);
330 FMT_(R16G16B16A16_SINT);
331 FMT2(R16G16B16A16_SFLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT);
332
333 FMT_(R32_UINT);
334 FMT_(R32_SINT);
335 FMT2(R32_SFLOAT, DXGI_FORMAT_R32_FLOAT);
336 FMT_(R32G32_UINT);
337 FMT_(R32G32_SINT);
338 FMT2(R32G32_SFLOAT, DXGI_FORMAT_R32G32_FLOAT);
339 FMT_(R32G32B32A32_UINT);
340 FMT_(R32G32B32A32_SINT);
341 FMT2(R32G32B32A32_SFLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT);
342
343 case SLANG_FORMAT_UNKNOWN:
344 default:
345 break;
346 }
347
348 return DXGI_FORMAT_UNKNOWN;
349 }
350