1 //-------------------------------------------------------------------------------------
2 // DirectXTexUtil.cpp
3 //
4 // DirectX Texture Library - Utilities
5 //
6 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
7 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
8 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
9 // PARTICULAR PURPOSE.
10 //
11 // Copyright (c) Microsoft Corporation. All rights reserved.
12 //
13 // http://go.microsoft.com/fwlink/?LinkId=248926
14 //-------------------------------------------------------------------------------------
15
16 #include "DirectXTexP.h"
17
18 //-------------------------------------------------------------------------------------
19 // WIC Pixel Format Translation Data
20 //-------------------------------------------------------------------------------------
21 struct WICTranslate
22 {
23 GUID wic;
24 DXGI_FORMAT format;
25 bool srgb;
26 };
27
28 static WICTranslate g_WICFormats[] =
29 {
30 { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
31
32 { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false },
33 { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM, true },
34
35 { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM, true },
36 { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM, true }, // DXGI 1.1
37 { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM, true }, // DXGI 1.1
38
39 { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true }, // DXGI 1.1
40 { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM, true },
41
42 { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM, true },
43 { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM, true },
44
45 { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT, false },
46 { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT, false },
47 { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM, true },
48 { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM, true },
49
50 { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM, false },
51
52 { GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false },
53 };
54
55 static bool g_WIC2 = false;
56
57 namespace DirectX
58 {
59
60 //=====================================================================================
61 // WIC Utilities
62 //=====================================================================================
63
64 _Use_decl_annotations_
_WICToDXGI(const GUID & guid)65 DXGI_FORMAT _WICToDXGI( const GUID& guid )
66 {
67 for( size_t i=0; i < _countof(g_WICFormats); ++i )
68 {
69 if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 )
70 return g_WICFormats[i].format;
71 }
72
73 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
74 if ( g_WIC2 )
75 {
76 if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 )
77 return DXGI_FORMAT_R32G32B32_FLOAT;
78 }
79 #endif
80
81 return DXGI_FORMAT_UNKNOWN;
82 }
83
84 _Use_decl_annotations_
_DXGIToWIC(DXGI_FORMAT format,GUID & guid,bool ignoreRGBvsBGR)85 bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
86 {
87 switch( format )
88 {
89 case DXGI_FORMAT_R8G8B8A8_UNORM:
90 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
91 if ( ignoreRGBvsBGR )
92 {
93 // If we are not doing conversion so don't really care about BGR vs RGB color-order,
94 // we can use the canonical WIC 32bppBGRA format which avoids an extra format conversion when using the WIC scaler
95 memcpy( &guid, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID) );
96 }
97 else
98 {
99 memcpy( &guid, &GUID_WICPixelFormat32bppRGBA, sizeof(GUID) );
100 }
101 return true;
102
103 case DXGI_FORMAT_D32_FLOAT:
104 memcpy( &guid, &GUID_WICPixelFormat32bppGrayFloat, sizeof(GUID) );
105 return true;
106
107 case DXGI_FORMAT_D16_UNORM:
108 memcpy( &guid, &GUID_WICPixelFormat16bppGray, sizeof(GUID) );
109 return true;
110
111 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
112 memcpy( &guid, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID) );
113 return true;
114
115 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
116 memcpy( &guid, &GUID_WICPixelFormat32bppBGR, sizeof(GUID) );
117 return true;
118
119 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
120 case DXGI_FORMAT_R32G32B32_FLOAT:
121 if ( g_WIC2 )
122 {
123 memcpy( &guid, &GUID_WICPixelFormat96bppRGBFloat, sizeof(GUID) );
124 return true;
125 }
126 break;
127 #endif
128
129 default:
130 for( size_t i=0; i < _countof(g_WICFormats); ++i )
131 {
132 if ( g_WICFormats[i].format == format )
133 {
134 memcpy( &guid, &g_WICFormats[i].wic, sizeof(GUID) );
135 return true;
136 }
137 }
138 break;
139 }
140
141 memcpy( &guid, &GUID_NULL, sizeof(GUID) );
142 return false;
143 }
144
_CheckWICColorSpace(_In_ const GUID & sourceGUID,_In_ const GUID & targetGUID)145 DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID )
146 {
147 DWORD srgb = 0;
148
149 for( size_t i=0; i < _countof(g_WICFormats); ++i )
150 {
151 if ( memcmp( &g_WICFormats[i].wic, &sourceGUID, sizeof(GUID) ) == 0 )
152 {
153 if ( g_WICFormats[i].srgb )
154 srgb |= TEX_FILTER_SRGB_IN;
155 }
156
157 if ( memcmp( &g_WICFormats[i].wic, &targetGUID, sizeof(GUID) ) == 0 )
158 {
159 if ( g_WICFormats[i].srgb )
160 srgb |= TEX_FILTER_SRGB_OUT;
161 }
162 }
163
164 if ( (srgb & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
165 {
166 srgb &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
167 }
168
169 return srgb;
170 }
171
_IsWIC2()172 bool _IsWIC2()
173 {
174 return g_WIC2;
175 }
176
_GetWIC()177 IWICImagingFactory* _GetWIC()
178 {
179 static IWICImagingFactory* s_Factory = nullptr;
180
181 if ( s_Factory )
182 return s_Factory;
183
184 #if(_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
185 HRESULT hr = CoCreateInstance(
186 CLSID_WICImagingFactory2,
187 nullptr,
188 CLSCTX_INPROC_SERVER,
189 __uuidof(IWICImagingFactory2),
190 (LPVOID*)&s_Factory
191 );
192
193 if ( SUCCEEDED(hr) )
194 {
195 // WIC2 is available on Windows 8 and Windows 7 SP1 with KB 2670838 installed
196 g_WIC2 = true;
197 }
198 else
199 {
200 hr = CoCreateInstance(
201 CLSID_WICImagingFactory1,
202 nullptr,
203 CLSCTX_INPROC_SERVER,
204 __uuidof(IWICImagingFactory),
205 (LPVOID*)&s_Factory
206 );
207
208 if ( FAILED(hr) )
209 {
210 s_Factory = nullptr;
211 return nullptr;
212 }
213 }
214 #else
215 HRESULT hr = CoCreateInstance(
216 CLSID_WICImagingFactory,
217 nullptr,
218 CLSCTX_INPROC_SERVER,
219 __uuidof(IWICImagingFactory),
220 (LPVOID*)&s_Factory
221 );
222
223 if ( FAILED(hr) )
224 {
225 s_Factory = nullptr;
226 return nullptr;
227 }
228 #endif
229
230 return s_Factory;
231 }
232
233
234 //-------------------------------------------------------------------------------------
235 // Public helper function to get common WIC codec GUIDs
236 //-------------------------------------------------------------------------------------
237 _Use_decl_annotations_
GetWICCodec(WICCodecs codec)238 REFGUID GetWICCodec( WICCodecs codec )
239 {
240 switch( codec )
241 {
242 case WIC_CODEC_BMP:
243 return GUID_ContainerFormatBmp;
244
245 case WIC_CODEC_JPEG:
246 return GUID_ContainerFormatJpeg;
247
248 case WIC_CODEC_PNG:
249 return GUID_ContainerFormatPng;
250
251 case WIC_CODEC_TIFF:
252 return GUID_ContainerFormatTiff;
253
254 case WIC_CODEC_GIF:
255 return GUID_ContainerFormatGif;
256
257 case WIC_CODEC_WMP:
258 return GUID_ContainerFormatWmp;
259
260 case WIC_CODEC_ICO:
261 return GUID_ContainerFormatIco;
262
263 default:
264 return GUID_NULL;
265 }
266 }
267
268
269 //=====================================================================================
270 // DXGI Format Utilities
271 //=====================================================================================
272
273 //-------------------------------------------------------------------------------------
274 // Returns bits-per-pixel for a given DXGI format, or 0 on failure
275 //-------------------------------------------------------------------------------------
276 _Use_decl_annotations_
BitsPerPixel(DXGI_FORMAT fmt)277 size_t BitsPerPixel( DXGI_FORMAT fmt )
278 {
279 switch( static_cast<int>(fmt) )
280 {
281 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
282 case DXGI_FORMAT_R32G32B32A32_FLOAT:
283 case DXGI_FORMAT_R32G32B32A32_UINT:
284 case DXGI_FORMAT_R32G32B32A32_SINT:
285 return 128;
286
287 case DXGI_FORMAT_R32G32B32_TYPELESS:
288 case DXGI_FORMAT_R32G32B32_FLOAT:
289 case DXGI_FORMAT_R32G32B32_UINT:
290 case DXGI_FORMAT_R32G32B32_SINT:
291 return 96;
292
293 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
294 case DXGI_FORMAT_R16G16B16A16_FLOAT:
295 case DXGI_FORMAT_R16G16B16A16_UNORM:
296 case DXGI_FORMAT_R16G16B16A16_UINT:
297 case DXGI_FORMAT_R16G16B16A16_SNORM:
298 case DXGI_FORMAT_R16G16B16A16_SINT:
299 case DXGI_FORMAT_R32G32_TYPELESS:
300 case DXGI_FORMAT_R32G32_FLOAT:
301 case DXGI_FORMAT_R32G32_UINT:
302 case DXGI_FORMAT_R32G32_SINT:
303 case DXGI_FORMAT_R32G8X24_TYPELESS:
304 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
305 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
306 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
307 case DXGI_FORMAT_Y416:
308 case DXGI_FORMAT_Y210:
309 case DXGI_FORMAT_Y216:
310 return 64;
311
312 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
313 case DXGI_FORMAT_R10G10B10A2_UNORM:
314 case DXGI_FORMAT_R10G10B10A2_UINT:
315 case DXGI_FORMAT_R11G11B10_FLOAT:
316 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
317 case DXGI_FORMAT_R8G8B8A8_UNORM:
318 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
319 case DXGI_FORMAT_R8G8B8A8_UINT:
320 case DXGI_FORMAT_R8G8B8A8_SNORM:
321 case DXGI_FORMAT_R8G8B8A8_SINT:
322 case DXGI_FORMAT_R16G16_TYPELESS:
323 case DXGI_FORMAT_R16G16_FLOAT:
324 case DXGI_FORMAT_R16G16_UNORM:
325 case DXGI_FORMAT_R16G16_UINT:
326 case DXGI_FORMAT_R16G16_SNORM:
327 case DXGI_FORMAT_R16G16_SINT:
328 case DXGI_FORMAT_R32_TYPELESS:
329 case DXGI_FORMAT_D32_FLOAT:
330 case DXGI_FORMAT_R32_FLOAT:
331 case DXGI_FORMAT_R32_UINT:
332 case DXGI_FORMAT_R32_SINT:
333 case DXGI_FORMAT_R24G8_TYPELESS:
334 case DXGI_FORMAT_D24_UNORM_S8_UINT:
335 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
336 case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
337 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
338 case DXGI_FORMAT_R8G8_B8G8_UNORM:
339 case DXGI_FORMAT_G8R8_G8B8_UNORM:
340 case DXGI_FORMAT_B8G8R8A8_UNORM:
341 case DXGI_FORMAT_B8G8R8X8_UNORM:
342 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
343 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
344 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
345 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
346 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
347 case DXGI_FORMAT_AYUV:
348 case DXGI_FORMAT_Y410:
349 case DXGI_FORMAT_YUY2:
350 case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
351 case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
352 return 32;
353
354 case DXGI_FORMAT_P010:
355 case DXGI_FORMAT_P016:
356 case 118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */:
357 case 119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */:
358 case 120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */:
359 return 24;
360
361 case DXGI_FORMAT_R8G8_TYPELESS:
362 case DXGI_FORMAT_R8G8_UNORM:
363 case DXGI_FORMAT_R8G8_UINT:
364 case DXGI_FORMAT_R8G8_SNORM:
365 case DXGI_FORMAT_R8G8_SINT:
366 case DXGI_FORMAT_R16_TYPELESS:
367 case DXGI_FORMAT_R16_FLOAT:
368 case DXGI_FORMAT_D16_UNORM:
369 case DXGI_FORMAT_R16_UNORM:
370 case DXGI_FORMAT_R16_UINT:
371 case DXGI_FORMAT_R16_SNORM:
372 case DXGI_FORMAT_R16_SINT:
373 case DXGI_FORMAT_B5G6R5_UNORM:
374 case DXGI_FORMAT_B5G5R5A1_UNORM:
375 case DXGI_FORMAT_A8P8:
376 case DXGI_FORMAT_B4G4R4A4_UNORM:
377 return 16;
378
379 case DXGI_FORMAT_NV12:
380 case DXGI_FORMAT_420_OPAQUE:
381 case DXGI_FORMAT_NV11:
382 return 12;
383
384 case DXGI_FORMAT_R8_TYPELESS:
385 case DXGI_FORMAT_R8_UNORM:
386 case DXGI_FORMAT_R8_UINT:
387 case DXGI_FORMAT_R8_SNORM:
388 case DXGI_FORMAT_R8_SINT:
389 case DXGI_FORMAT_A8_UNORM:
390 case DXGI_FORMAT_AI44:
391 case DXGI_FORMAT_IA44:
392 case DXGI_FORMAT_P8:
393 return 8;
394
395 case DXGI_FORMAT_R1_UNORM:
396 return 1;
397
398 case DXGI_FORMAT_BC1_TYPELESS:
399 case DXGI_FORMAT_BC1_UNORM:
400 case DXGI_FORMAT_BC1_UNORM_SRGB:
401 case DXGI_FORMAT_BC4_TYPELESS:
402 case DXGI_FORMAT_BC4_UNORM:
403 case DXGI_FORMAT_BC4_SNORM:
404 return 4;
405
406 case DXGI_FORMAT_BC2_TYPELESS:
407 case DXGI_FORMAT_BC2_UNORM:
408 case DXGI_FORMAT_BC2_UNORM_SRGB:
409 case DXGI_FORMAT_BC3_TYPELESS:
410 case DXGI_FORMAT_BC3_UNORM:
411 case DXGI_FORMAT_BC3_UNORM_SRGB:
412 case DXGI_FORMAT_BC5_TYPELESS:
413 case DXGI_FORMAT_BC5_UNORM:
414 case DXGI_FORMAT_BC5_SNORM:
415 case DXGI_FORMAT_BC6H_TYPELESS:
416 case DXGI_FORMAT_BC6H_UF16:
417 case DXGI_FORMAT_BC6H_SF16:
418 case DXGI_FORMAT_BC7_TYPELESS:
419 case DXGI_FORMAT_BC7_UNORM:
420 case DXGI_FORMAT_BC7_UNORM_SRGB:
421 return 8;
422
423 default:
424 return 0;
425 }
426 }
427
428
429 //-------------------------------------------------------------------------------------
430 // Returns bits-per-color-channel for a given DXGI format, or 0 on failure
431 // For mixed formats, it returns the largest color-depth in the format
432 //-------------------------------------------------------------------------------------
433 _Use_decl_annotations_
BitsPerColor(DXGI_FORMAT fmt)434 size_t BitsPerColor( DXGI_FORMAT fmt )
435 {
436 switch( static_cast<int>(fmt) )
437 {
438 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
439 case DXGI_FORMAT_R32G32B32A32_FLOAT:
440 case DXGI_FORMAT_R32G32B32A32_UINT:
441 case DXGI_FORMAT_R32G32B32A32_SINT:
442 case DXGI_FORMAT_R32G32B32_TYPELESS:
443 case DXGI_FORMAT_R32G32B32_FLOAT:
444 case DXGI_FORMAT_R32G32B32_UINT:
445 case DXGI_FORMAT_R32G32B32_SINT:
446 case DXGI_FORMAT_R32G32_TYPELESS:
447 case DXGI_FORMAT_R32G32_FLOAT:
448 case DXGI_FORMAT_R32G32_UINT:
449 case DXGI_FORMAT_R32G32_SINT:
450 case DXGI_FORMAT_R32G8X24_TYPELESS:
451 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
452 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
453 case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
454 case DXGI_FORMAT_R32_TYPELESS:
455 case DXGI_FORMAT_D32_FLOAT:
456 case DXGI_FORMAT_R32_FLOAT:
457 case DXGI_FORMAT_R32_UINT:
458 case DXGI_FORMAT_R32_SINT:
459 return 32;
460
461 case DXGI_FORMAT_R24G8_TYPELESS:
462 case DXGI_FORMAT_D24_UNORM_S8_UINT:
463 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
464 case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
465 return 24;
466
467 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
468 case DXGI_FORMAT_R16G16B16A16_FLOAT:
469 case DXGI_FORMAT_R16G16B16A16_UNORM:
470 case DXGI_FORMAT_R16G16B16A16_UINT:
471 case DXGI_FORMAT_R16G16B16A16_SNORM:
472 case DXGI_FORMAT_R16G16B16A16_SINT:
473 case DXGI_FORMAT_R16G16_TYPELESS:
474 case DXGI_FORMAT_R16G16_FLOAT:
475 case DXGI_FORMAT_R16G16_UNORM:
476 case DXGI_FORMAT_R16G16_UINT:
477 case DXGI_FORMAT_R16G16_SNORM:
478 case DXGI_FORMAT_R16G16_SINT:
479 case DXGI_FORMAT_R16_TYPELESS:
480 case DXGI_FORMAT_R16_FLOAT:
481 case DXGI_FORMAT_D16_UNORM:
482 case DXGI_FORMAT_R16_UNORM:
483 case DXGI_FORMAT_R16_UINT:
484 case DXGI_FORMAT_R16_SNORM:
485 case DXGI_FORMAT_R16_SINT:
486 case DXGI_FORMAT_BC6H_TYPELESS:
487 case DXGI_FORMAT_BC6H_UF16:
488 case DXGI_FORMAT_BC6H_SF16:
489 case DXGI_FORMAT_Y416:
490 case DXGI_FORMAT_P016:
491 case DXGI_FORMAT_Y216:
492 return 16;
493
494 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
495 return 14;
496
497 case DXGI_FORMAT_R11G11B10_FLOAT:
498 return 11;
499
500 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
501 case DXGI_FORMAT_R10G10B10A2_UNORM:
502 case DXGI_FORMAT_R10G10B10A2_UINT:
503 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
504 case DXGI_FORMAT_Y410:
505 case DXGI_FORMAT_P010:
506 case DXGI_FORMAT_Y210:
507 return 10;
508
509 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
510 case DXGI_FORMAT_R8G8B8A8_UNORM:
511 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
512 case DXGI_FORMAT_R8G8B8A8_UINT:
513 case DXGI_FORMAT_R8G8B8A8_SNORM:
514 case DXGI_FORMAT_R8G8B8A8_SINT:
515 case DXGI_FORMAT_R8G8_TYPELESS:
516 case DXGI_FORMAT_R8G8_UNORM:
517 case DXGI_FORMAT_R8G8_UINT:
518 case DXGI_FORMAT_R8G8_SNORM:
519 case DXGI_FORMAT_R8G8_SINT:
520 case DXGI_FORMAT_R8_TYPELESS:
521 case DXGI_FORMAT_R8_UNORM:
522 case DXGI_FORMAT_R8_UINT:
523 case DXGI_FORMAT_R8_SNORM:
524 case DXGI_FORMAT_R8_SINT:
525 case DXGI_FORMAT_A8_UNORM:
526 case DXGI_FORMAT_R8G8_B8G8_UNORM:
527 case DXGI_FORMAT_G8R8_G8B8_UNORM:
528 case DXGI_FORMAT_BC4_TYPELESS:
529 case DXGI_FORMAT_BC4_UNORM:
530 case DXGI_FORMAT_BC4_SNORM:
531 case DXGI_FORMAT_BC5_TYPELESS:
532 case DXGI_FORMAT_BC5_UNORM:
533 case DXGI_FORMAT_BC5_SNORM:
534 case DXGI_FORMAT_B8G8R8A8_UNORM:
535 case DXGI_FORMAT_B8G8R8X8_UNORM:
536 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
537 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
538 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
539 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
540 case DXGI_FORMAT_AYUV:
541 case DXGI_FORMAT_NV12:
542 case DXGI_FORMAT_420_OPAQUE:
543 case DXGI_FORMAT_YUY2:
544 case DXGI_FORMAT_NV11:
545 return 8;
546
547 case DXGI_FORMAT_BC7_TYPELESS:
548 case DXGI_FORMAT_BC7_UNORM:
549 case DXGI_FORMAT_BC7_UNORM_SRGB:
550 return 7;
551
552 case DXGI_FORMAT_BC1_TYPELESS:
553 case DXGI_FORMAT_BC1_UNORM:
554 case DXGI_FORMAT_BC1_UNORM_SRGB:
555 case DXGI_FORMAT_BC2_TYPELESS:
556 case DXGI_FORMAT_BC2_UNORM:
557 case DXGI_FORMAT_BC2_UNORM_SRGB:
558 case DXGI_FORMAT_BC3_TYPELESS:
559 case DXGI_FORMAT_BC3_UNORM:
560 case DXGI_FORMAT_BC3_UNORM_SRGB:
561 case DXGI_FORMAT_B5G6R5_UNORM:
562 return 6;
563
564 case DXGI_FORMAT_B5G5R5A1_UNORM:
565 return 5;
566
567 case DXGI_FORMAT_B4G4R4A4_UNORM:
568 return 4;
569
570 case DXGI_FORMAT_R1_UNORM:
571 return 1;
572
573 case 116 /* DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT */:
574 case 117 /* DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT */:
575 // These are Xbox One platform specific types
576 return 10;
577
578 case 118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */:
579 case 119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */:
580 case 120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */:
581 // These are Xbox One platform specific types
582 return 16;
583
584 case DXGI_FORMAT_AI44:
585 case DXGI_FORMAT_IA44:
586 case DXGI_FORMAT_P8:
587 case DXGI_FORMAT_A8P8:
588 // Palettized formats return 0 for this function
589
590 default:
591 return 0;
592 }
593 }
594
595
596 //-------------------------------------------------------------------------------------
597 // Computes the image row pitch in bytes, and the slice ptich (size in bytes of the image)
598 // based on DXGI format, width, and height
599 //-------------------------------------------------------------------------------------
600 _Use_decl_annotations_
ComputePitch(DXGI_FORMAT fmt,size_t width,size_t height,size_t & rowPitch,size_t & slicePitch,DWORD flags)601 void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
602 size_t& rowPitch, size_t& slicePitch, DWORD flags )
603 {
604 assert( IsValid(fmt) );
605
606 if ( IsCompressed(fmt) )
607 {
608 size_t bpb = ( fmt == DXGI_FORMAT_BC1_TYPELESS
609 || fmt == DXGI_FORMAT_BC1_UNORM
610 || fmt == DXGI_FORMAT_BC1_UNORM_SRGB
611 || fmt == DXGI_FORMAT_BC4_TYPELESS
612 || fmt == DXGI_FORMAT_BC4_UNORM
613 || fmt == DXGI_FORMAT_BC4_SNORM) ? 8 : 16;
614 size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
615 size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
616 rowPitch = nbw * bpb;
617
618 slicePitch = rowPitch * nbh;
619 }
620 else if ( IsPacked(fmt) )
621 {
622 size_t bpe = ( fmt == DXGI_FORMAT_Y210 || fmt == DXGI_FORMAT_Y216 ) ? 8 : 4;
623 rowPitch = ( ( width + 1 ) >> 1 ) * bpe;
624
625 slicePitch = rowPitch * height;
626 }
627 else if ( fmt == DXGI_FORMAT_NV11 )
628 {
629 rowPitch = ( ( width + 3 ) >> 2 ) * 4;
630
631 // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
632 slicePitch = rowPitch * height * 2;
633 }
634 else if ( IsPlanar(fmt) )
635 {
636 size_t bpe = ( fmt == DXGI_FORMAT_P010 || fmt == DXGI_FORMAT_P016
637 || fmt == DXGI_FORMAT(118 /* DXGI_FORMAT_D16_UNORM_S8_UINT */)
638 || fmt == DXGI_FORMAT(119 /* DXGI_FORMAT_R16_UNORM_X8_TYPELESS */)
639 || fmt == DXGI_FORMAT(120 /* DXGI_FORMAT_X16_TYPELESS_G8_UINT */) ) ? 4 : 2;
640 rowPitch = ( ( width + 1 ) >> 1 ) * bpe;
641
642 slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
643 }
644 else
645 {
646 size_t bpp;
647
648 if ( flags & CP_FLAGS_24BPP )
649 bpp = 24;
650 else if ( flags & CP_FLAGS_16BPP )
651 bpp = 16;
652 else if ( flags & CP_FLAGS_8BPP )
653 bpp = 8;
654 else
655 bpp = BitsPerPixel( fmt );
656
657 if ( flags & ( CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K ) )
658 {
659 if ( flags & CP_FLAGS_PAGE4K )
660 {
661 rowPitch = ( ( width * bpp + 32767 ) / 32768 ) * 4096;
662 slicePitch = rowPitch * height;
663 }
664 else if ( flags & CP_FLAGS_ZMM )
665 {
666 rowPitch = ( ( width * bpp + 511 ) / 512 ) * 64;
667 slicePitch = rowPitch * height;
668 }
669 else if ( flags & CP_FLAGS_YMM )
670 {
671 rowPitch = ( ( width * bpp + 255 ) / 256) * 32;
672 slicePitch = rowPitch * height;
673 }
674 else if ( flags & CP_FLAGS_PARAGRAPH )
675 {
676 rowPitch = ( ( width * bpp + 127 ) / 128 ) * 16;
677 slicePitch = rowPitch * height;
678 }
679 else // DWORD alignment
680 {
681 // Special computation for some incorrectly created DDS files based on
682 // legacy DirectDraw assumptions about pitch alignment
683 rowPitch = ( ( width * bpp + 31 ) / 32 ) * sizeof(uint32_t);
684 slicePitch = rowPitch * height;
685 }
686 }
687 else
688 {
689 // Default byte alignment
690 rowPitch = ( width * bpp + 7 ) / 8;
691 slicePitch = rowPitch * height;
692 }
693 }
694 }
695
696
697 //-------------------------------------------------------------------------------------
698 // Converts to an SRGB equivalent type if available
699 //-------------------------------------------------------------------------------------
700 _Use_decl_annotations_
MakeSRGB(DXGI_FORMAT fmt)701 DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
702 {
703 switch( fmt )
704 {
705 case DXGI_FORMAT_R8G8B8A8_UNORM:
706 return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
707
708 case DXGI_FORMAT_BC1_UNORM:
709 return DXGI_FORMAT_BC1_UNORM_SRGB;
710
711 case DXGI_FORMAT_BC2_UNORM:
712 return DXGI_FORMAT_BC2_UNORM_SRGB;
713
714 case DXGI_FORMAT_BC3_UNORM:
715 return DXGI_FORMAT_BC3_UNORM_SRGB;
716
717 case DXGI_FORMAT_B8G8R8A8_UNORM:
718 return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
719
720 case DXGI_FORMAT_B8G8R8X8_UNORM:
721 return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
722
723 case DXGI_FORMAT_BC7_UNORM:
724 return DXGI_FORMAT_BC7_UNORM_SRGB;
725
726 default:
727 return fmt;
728 }
729 }
730
731
732 //-------------------------------------------------------------------------------------
733 // Converts to a format to an equivalent TYPELESS format if available
734 //-------------------------------------------------------------------------------------
735 _Use_decl_annotations_
MakeTypeless(DXGI_FORMAT fmt)736 DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
737 {
738 switch( fmt )
739 {
740 case DXGI_FORMAT_R32G32B32A32_FLOAT:
741 case DXGI_FORMAT_R32G32B32A32_UINT:
742 case DXGI_FORMAT_R32G32B32A32_SINT:
743 return DXGI_FORMAT_R32G32B32A32_TYPELESS;
744
745 case DXGI_FORMAT_R32G32B32_FLOAT:
746 case DXGI_FORMAT_R32G32B32_UINT:
747 case DXGI_FORMAT_R32G32B32_SINT:
748 return DXGI_FORMAT_R32G32B32_TYPELESS;
749
750 case DXGI_FORMAT_R16G16B16A16_FLOAT:
751 case DXGI_FORMAT_R16G16B16A16_UNORM:
752 case DXGI_FORMAT_R16G16B16A16_UINT:
753 case DXGI_FORMAT_R16G16B16A16_SNORM:
754 case DXGI_FORMAT_R16G16B16A16_SINT:
755 return DXGI_FORMAT_R16G16B16A16_TYPELESS;
756
757 case DXGI_FORMAT_R32G32_FLOAT:
758 case DXGI_FORMAT_R32G32_UINT:
759 case DXGI_FORMAT_R32G32_SINT:
760 return DXGI_FORMAT_R32G32_TYPELESS;
761
762 case DXGI_FORMAT_R10G10B10A2_UNORM:
763 case DXGI_FORMAT_R10G10B10A2_UINT:
764 return DXGI_FORMAT_R10G10B10A2_TYPELESS;
765
766 case DXGI_FORMAT_R8G8B8A8_UNORM:
767 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
768 case DXGI_FORMAT_R8G8B8A8_UINT:
769 case DXGI_FORMAT_R8G8B8A8_SNORM:
770 case DXGI_FORMAT_R8G8B8A8_SINT:
771 return DXGI_FORMAT_R8G8B8A8_TYPELESS;
772
773 case DXGI_FORMAT_R16G16_FLOAT:
774 case DXGI_FORMAT_R16G16_UNORM:
775 case DXGI_FORMAT_R16G16_UINT:
776 case DXGI_FORMAT_R16G16_SNORM:
777 case DXGI_FORMAT_R16G16_SINT:
778 return DXGI_FORMAT_R16G16_TYPELESS;
779
780 case DXGI_FORMAT_D32_FLOAT:
781 case DXGI_FORMAT_R32_FLOAT:
782 case DXGI_FORMAT_R32_UINT:
783 case DXGI_FORMAT_R32_SINT:
784 return DXGI_FORMAT_R32_TYPELESS;
785
786 case DXGI_FORMAT_R8G8_UNORM:
787 case DXGI_FORMAT_R8G8_UINT:
788 case DXGI_FORMAT_R8G8_SNORM:
789 case DXGI_FORMAT_R8G8_SINT:
790 return DXGI_FORMAT_R8G8_TYPELESS;
791
792 case DXGI_FORMAT_R16_FLOAT:
793 case DXGI_FORMAT_D16_UNORM:
794 case DXGI_FORMAT_R16_UNORM:
795 case DXGI_FORMAT_R16_UINT:
796 case DXGI_FORMAT_R16_SNORM:
797 case DXGI_FORMAT_R16_SINT:
798 return DXGI_FORMAT_R16_TYPELESS;
799
800 case DXGI_FORMAT_R8_UNORM:
801 case DXGI_FORMAT_R8_UINT:
802 case DXGI_FORMAT_R8_SNORM:
803 case DXGI_FORMAT_R8_SINT:
804 return DXGI_FORMAT_R8_TYPELESS;
805
806 case DXGI_FORMAT_BC1_UNORM:
807 case DXGI_FORMAT_BC1_UNORM_SRGB:
808 return DXGI_FORMAT_BC1_TYPELESS;
809
810 case DXGI_FORMAT_BC2_UNORM:
811 case DXGI_FORMAT_BC2_UNORM_SRGB:
812 return DXGI_FORMAT_BC2_TYPELESS;
813
814 case DXGI_FORMAT_BC3_UNORM:
815 case DXGI_FORMAT_BC3_UNORM_SRGB:
816 return DXGI_FORMAT_BC3_TYPELESS;
817
818 case DXGI_FORMAT_BC4_UNORM:
819 case DXGI_FORMAT_BC4_SNORM:
820 return DXGI_FORMAT_BC4_TYPELESS;
821
822 case DXGI_FORMAT_BC5_UNORM:
823 case DXGI_FORMAT_BC5_SNORM:
824 return DXGI_FORMAT_BC5_TYPELESS;
825
826 case DXGI_FORMAT_B8G8R8A8_UNORM:
827 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
828 return DXGI_FORMAT_B8G8R8A8_TYPELESS;
829
830 case DXGI_FORMAT_B8G8R8X8_UNORM:
831 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
832 return DXGI_FORMAT_B8G8R8X8_TYPELESS;
833
834 case DXGI_FORMAT_BC6H_UF16:
835 case DXGI_FORMAT_BC6H_SF16:
836 return DXGI_FORMAT_BC6H_TYPELESS;
837
838 case DXGI_FORMAT_BC7_UNORM:
839 case DXGI_FORMAT_BC7_UNORM_SRGB:
840 return DXGI_FORMAT_BC7_TYPELESS;
841
842 default:
843 return fmt;
844 }
845 }
846
847
848 //-------------------------------------------------------------------------------------
849 // Converts to a TYPELESS format to an equivalent UNORM format if available
850 //-------------------------------------------------------------------------------------
851 _Use_decl_annotations_
MakeTypelessUNORM(DXGI_FORMAT fmt)852 DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
853 {
854 switch( fmt )
855 {
856 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
857 return DXGI_FORMAT_R16G16B16A16_UNORM;
858
859 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
860 return DXGI_FORMAT_R10G10B10A2_UNORM;
861
862 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
863 return DXGI_FORMAT_R8G8B8A8_UNORM;
864
865 case DXGI_FORMAT_R16G16_TYPELESS:
866 return DXGI_FORMAT_R16G16_UNORM;
867
868 case DXGI_FORMAT_R8G8_TYPELESS:
869 return DXGI_FORMAT_R8G8_UNORM;
870
871 case DXGI_FORMAT_R16_TYPELESS:
872 return DXGI_FORMAT_R16_UNORM;
873
874 case DXGI_FORMAT_R8_TYPELESS:
875 return DXGI_FORMAT_R8_UNORM;
876
877 case DXGI_FORMAT_BC1_TYPELESS:
878 return DXGI_FORMAT_BC1_UNORM;
879
880 case DXGI_FORMAT_BC2_TYPELESS:
881 return DXGI_FORMAT_BC2_UNORM;
882
883 case DXGI_FORMAT_BC3_TYPELESS:
884 return DXGI_FORMAT_BC3_UNORM;
885
886 case DXGI_FORMAT_BC4_TYPELESS:
887 return DXGI_FORMAT_BC4_UNORM;
888
889 case DXGI_FORMAT_BC5_TYPELESS:
890 return DXGI_FORMAT_BC5_UNORM;
891
892 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
893 return DXGI_FORMAT_B8G8R8A8_UNORM;
894
895 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
896 return DXGI_FORMAT_B8G8R8X8_UNORM;
897
898 case DXGI_FORMAT_BC7_TYPELESS:
899 return DXGI_FORMAT_BC7_UNORM;
900
901 default:
902 return fmt;
903 }
904 }
905
906
907 //-------------------------------------------------------------------------------------
908 // Converts to a TYPELESS format to an equivalent FLOAT format if available
909 //-------------------------------------------------------------------------------------
910 _Use_decl_annotations_
MakeTypelessFLOAT(DXGI_FORMAT fmt)911 DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
912 {
913 switch( fmt )
914 {
915 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
916 return DXGI_FORMAT_R32G32B32A32_FLOAT;
917
918 case DXGI_FORMAT_R32G32B32_TYPELESS:
919 return DXGI_FORMAT_R32G32B32_FLOAT;
920
921 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
922 return DXGI_FORMAT_R16G16B16A16_FLOAT;
923
924 case DXGI_FORMAT_R32G32_TYPELESS:
925 return DXGI_FORMAT_R32G32_FLOAT;
926
927 case DXGI_FORMAT_R16G16_TYPELESS:
928 return DXGI_FORMAT_R16G16_FLOAT;
929
930 case DXGI_FORMAT_R32_TYPELESS:
931 return DXGI_FORMAT_R32_FLOAT;
932
933 case DXGI_FORMAT_R16_TYPELESS:
934 return DXGI_FORMAT_R16_FLOAT;
935
936 default:
937 return fmt;
938 }
939 }
940
941
942 //=====================================================================================
943 // TexMetadata
944 //=====================================================================================
945
946 _Use_decl_annotations_
ComputeIndex(size_t mip,size_t item,size_t slice) const947 size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
948 {
949 if ( mip >= mipLevels )
950 return size_t(-1);
951
952 switch( dimension )
953 {
954 case TEX_DIMENSION_TEXTURE1D:
955 case TEX_DIMENSION_TEXTURE2D:
956 if ( slice > 0 )
957 return size_t(-1);
958
959 if ( item >= arraySize )
960 return size_t(-1);
961
962 return (item*( mipLevels ) + mip);
963
964 case TEX_DIMENSION_TEXTURE3D:
965 if ( item > 0 )
966 {
967 // No support for arrays of volumes
968 return size_t(-1);
969 }
970 else
971 {
972 size_t index = 0;
973 size_t d = depth;
974
975 for( size_t level = 0; level < mip; ++level )
976 {
977 index += d;
978 if ( d > 1 )
979 d >>= 1;
980 }
981
982 if ( slice >= d )
983 return size_t(-1);
984
985 index += slice;
986
987 return index;
988 }
989 break;
990
991 default:
992 return size_t(-1);
993 }
994 }
995
996
997 //=====================================================================================
998 // Blob - Bitmap image container
999 //=====================================================================================
1000
operator =(Blob && moveFrom)1001 Blob& Blob::operator= (Blob&& moveFrom)
1002 {
1003 if ( this != &moveFrom )
1004 {
1005 Release();
1006
1007 _buffer = moveFrom._buffer;
1008 _size = moveFrom._size;
1009
1010 moveFrom._buffer = nullptr;
1011 moveFrom._size = 0;
1012 }
1013 return *this;
1014 }
1015
Release()1016 void Blob::Release()
1017 {
1018 if ( _buffer )
1019 {
1020 _aligned_free( _buffer );
1021 _buffer = nullptr;
1022 }
1023
1024 _size = 0;
1025 }
1026
1027 _Use_decl_annotations_
Initialize(size_t size)1028 HRESULT Blob::Initialize( size_t size )
1029 {
1030 if ( !size )
1031 return E_INVALIDARG;
1032
1033 Release();
1034
1035 _buffer = _aligned_malloc( size, 16 );
1036 if ( !_buffer )
1037 {
1038 Release();
1039 return E_OUTOFMEMORY;
1040 }
1041
1042 _size = size;
1043
1044 return S_OK;
1045 }
1046
1047 }; // namespace
1048