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