]> git.cworth.org Git - apitrace/blob - thirdparty/directxtex/DirectXTex/DirectXTexConvert.cpp
directxtex: Fix assertion failures on MinGW.
[apitrace] / thirdparty / directxtex / DirectXTex / DirectXTexConvert.cpp
1 //-------------------------------------------------------------------------------------
2 // DirectXTexConvert.cpp
3 //  
4 // DirectX Texture Library - Image conversion 
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 #ifdef USE_XNAMATH
19 #if XNAMATH_VERSION < 205
20 #error This file requires XNAMATH v2.05 or later
21 #endif
22 #else
23 using namespace DirectX::PackedVector;
24 #endif
25
26 namespace DirectX
27 {
28
29 //-------------------------------------------------------------------------------------
30 // Copies an image row with optional clearing of alpha value to 1.0
31 // (can be used in place as well) otherwise copies the image row unmodified.
32 //-------------------------------------------------------------------------------------
33 void _CopyScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t inSize, DXGI_FORMAT format, DWORD flags )
34 {
35     assert( pDestination && outSize > 0 );
36     assert( pSource && inSize > 0 );
37     assert( IsValid(format) && !IsVideo(format) );
38
39     if ( flags & TEXP_SCANLINE_SETALPHA )
40     {
41         switch( format )
42         {
43         //-----------------------------------------------------------------------------
44         case DXGI_FORMAT_R32G32B32A32_TYPELESS:
45         case DXGI_FORMAT_R32G32B32A32_FLOAT:
46         case DXGI_FORMAT_R32G32B32A32_UINT:
47         case DXGI_FORMAT_R32G32B32A32_SINT:
48             {
49                 uint32_t alpha;
50                 if ( format == DXGI_FORMAT_R32G32B32A32_FLOAT )
51                     alpha = 0x3f800000;
52                 else if ( format == DXGI_FORMAT_R32G32B32A32_SINT )
53                     alpha = 0x7fffffff;
54                 else
55                     alpha = 0xffffffff;
56
57                 if ( pDestination == pSource )
58                 {
59                     uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
60                     for( size_t count = 0; count < outSize; count += 16 )
61                     {
62                         dPtr += 3;
63                         *(dPtr++) = alpha;
64                     }
65                 }
66                 else
67                 {
68                     const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
69                     uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
70                     size_t size = std::min<size_t>( outSize, inSize );
71                     for( size_t count = 0; count < size; count += 16 )
72                     {
73                         *(dPtr++) = *(sPtr++);
74                         *(dPtr++) = *(sPtr++);
75                         *(dPtr++) = *(sPtr++);
76                         *(dPtr++) = alpha;
77                         sPtr++;
78                     }
79                 }
80             }
81             return;
82
83         //-----------------------------------------------------------------------------
84         case DXGI_FORMAT_R16G16B16A16_TYPELESS:
85         case DXGI_FORMAT_R16G16B16A16_FLOAT:
86         case DXGI_FORMAT_R16G16B16A16_UNORM:
87         case DXGI_FORMAT_R16G16B16A16_UINT:
88         case DXGI_FORMAT_R16G16B16A16_SNORM:
89         case DXGI_FORMAT_R16G16B16A16_SINT:
90             {
91                 uint16_t alpha;
92                 if ( format == DXGI_FORMAT_R16G16B16A16_FLOAT )
93                     alpha = 0x3c00;
94                 else if ( format == DXGI_FORMAT_R16G16B16A16_SNORM || format == DXGI_FORMAT_R16G16B16A16_SINT )
95                     alpha = 0x7fff;
96                 else
97                     alpha = 0xffff;
98
99                 if ( pDestination == pSource )
100                 {
101                     uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
102                     for( size_t count = 0; count < outSize; count += 8 )
103                     {
104                         dPtr += 3;
105                         *(dPtr++) = alpha;
106                     }
107                 }
108                 else
109                 {
110                     const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
111                     uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
112                     size_t size = std::min<size_t>( outSize, inSize );
113                     for( size_t count = 0; count < size; count += 8 )
114                     {
115                         *(dPtr++) = *(sPtr++);
116                         *(dPtr++) = *(sPtr++);
117                         *(dPtr++) = *(sPtr++);
118                         *(dPtr++) = alpha;
119                         sPtr++;
120                     }
121                 }
122             }
123             return;
124
125         //-----------------------------------------------------------------------------
126         case DXGI_FORMAT_R10G10B10A2_TYPELESS:
127         case DXGI_FORMAT_R10G10B10A2_UNORM:
128         case DXGI_FORMAT_R10G10B10A2_UINT:
129         case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
130             if ( pDestination == pSource )
131             {
132                 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
133                 for( size_t count = 0; count < outSize; count += 4 )
134                 {
135 #pragma warning(suppress: 6001 6101) // PREFast doesn't properly understand the aliasing here.
136                     *dPtr |= 0xC0000000;
137                     ++dPtr;
138                 }
139             }
140             else
141             {
142                 const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
143                 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
144                 size_t size = std::min<size_t>( outSize, inSize );
145                 for( size_t count = 0; count < size; count += 4 )
146                 {
147                     *(dPtr++) = *(sPtr++) | 0xC0000000;
148                 }
149             }
150             return;
151
152         //-----------------------------------------------------------------------------
153         case DXGI_FORMAT_R8G8B8A8_TYPELESS:
154         case DXGI_FORMAT_R8G8B8A8_UNORM:
155         case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
156         case DXGI_FORMAT_R8G8B8A8_UINT:
157         case DXGI_FORMAT_R8G8B8A8_SNORM:
158         case DXGI_FORMAT_R8G8B8A8_SINT:
159         case DXGI_FORMAT_B8G8R8A8_UNORM:
160         case DXGI_FORMAT_B8G8R8A8_TYPELESS:
161         case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
162             {
163                 const uint32_t alpha = ( format == DXGI_FORMAT_R8G8B8A8_SNORM || format == DXGI_FORMAT_R8G8B8A8_SINT ) ? 0x7f000000 : 0xff000000;
164
165                 if ( pDestination == pSource )
166                 {
167                     uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
168                     for( size_t count = 0; count < outSize; count += 4 )
169                     {
170                         uint32_t t = *dPtr & 0xFFFFFF;
171                         t |= alpha;
172                         *(dPtr++) = t;
173                     }
174                 }
175                 else
176                 {
177                     const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
178                     uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
179                     size_t size = std::min<size_t>( outSize, inSize );
180                     for( size_t count = 0; count < size; count += 4 )
181                     {
182                         uint32_t t = *(sPtr++) & 0xFFFFFF;
183                         t |= alpha;
184                         *(dPtr++) = t;
185                     }
186                 }
187             }
188             return;
189
190         //-----------------------------------------------------------------------------
191         case DXGI_FORMAT_B5G5R5A1_UNORM:
192             if ( pDestination == pSource )
193             {
194                 uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
195                 for( size_t count = 0; count < outSize; count += 2 )
196                 {
197                     *(dPtr++) |= 0x8000;
198                 }
199             }
200             else
201             {
202                 const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
203                 uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
204                 size_t size = std::min<size_t>( outSize, inSize );
205                 for( size_t count = 0; count < size; count += 2 )
206                 {
207                     *(dPtr++) = *(sPtr++) | 0x8000;
208                 }
209             }
210             return;
211
212         //-----------------------------------------------------------------------------
213         case DXGI_FORMAT_A8_UNORM:
214             memset( pDestination, 0xff, outSize );
215             return;
216
217 #ifdef DXGI_1_2_FORMATS
218         //-----------------------------------------------------------------------------
219         case DXGI_FORMAT_B4G4R4A4_UNORM:
220             if ( pDestination == pSource )
221             {
222                 uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
223                 for( size_t count = 0; count < outSize; count += 2 )
224                 {
225                     *(dPtr++) |= 0xF000;
226                 }
227             }
228             else
229             {
230                 const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
231                 uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
232                 size_t size = std::min<size_t>( outSize, inSize );
233                 for( size_t count = 0; count < size; count += 2 )
234                 {
235                     *(dPtr++) = *(sPtr++) | 0xF000;
236                 }
237             }
238             return;
239 #endif // DXGI_1_2_FORMATS
240         }
241     }
242
243     // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
244     if ( pDestination == pSource )
245         return;
246
247     size_t size = std::min<size_t>( outSize, inSize );
248     memcpy_s( pDestination, outSize, pSource, size );
249 }
250
251
252 //-------------------------------------------------------------------------------------
253 // Swizzles (RGB <-> BGR) an image row with optional clearing of alpha value to 1.0
254 // (can be used in place as well) otherwise copies the image row unmodified.
255 //-------------------------------------------------------------------------------------
256 void _SwizzleScanline( LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t inSize, DXGI_FORMAT format, DWORD flags )
257 {
258     assert( pDestination && outSize > 0 );
259     assert( pSource && inSize > 0 );
260     assert( IsValid(format) && !IsVideo(format) );
261
262     switch( format )
263     {
264     //---------------------------------------------------------------------------------
265     case DXGI_FORMAT_R10G10B10A2_TYPELESS:
266     case DXGI_FORMAT_R10G10B10A2_UNORM:
267     case DXGI_FORMAT_R10G10B10A2_UINT:
268     case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
269         if ( flags & TEXP_SCANLINE_LEGACY )
270         {
271             // Swap Red (R) and Blue (B) channel (used for D3DFMT_A2R10G10B10 legacy sources)
272             if ( pDestination == pSource )
273             {
274                 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
275                 for( size_t count = 0; count < outSize; count += 4 )
276                 {
277 #pragma warning(suppress: 6001 6101) // PREFast doesn't properly understand the aliasing here.
278                     uint32_t t = *dPtr;
279
280                     uint32_t t1 = (t & 0x3ff00000) >> 20;
281                     uint32_t t2 = (t & 0x000003ff) << 20;
282                     uint32_t t3 = (t & 0x000ffc00);
283                     uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xC0000000 : (t & 0xC0000000);
284
285                     *(dPtr++) = t1 | t2 | t3 | ta;
286                 }
287             }
288             else
289             {
290                 const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
291                 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
292                 size_t size = std::min<size_t>( outSize, inSize );
293                 for( size_t count = 0; count < size; count += 4 )
294                 {
295                     uint32_t t = *(sPtr++);
296
297                     uint32_t t1 = (t & 0x3ff00000) >> 20;
298                     uint32_t t2 = (t & 0x000003ff) << 20;
299                     uint32_t t3 = (t & 0x000ffc00);
300                     uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xC0000000 : (t & 0xC0000000);
301
302                     *(dPtr++) = t1 | t2 | t3 | ta;
303                 }
304             }
305             return;
306         }
307         break;
308
309     //---------------------------------------------------------------------------------
310     case DXGI_FORMAT_R8G8B8A8_TYPELESS:
311     case DXGI_FORMAT_R8G8B8A8_UNORM:
312     case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
313     case DXGI_FORMAT_B8G8R8A8_UNORM:
314     case DXGI_FORMAT_B8G8R8X8_UNORM:
315     case DXGI_FORMAT_B8G8R8A8_TYPELESS:
316     case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
317     case DXGI_FORMAT_B8G8R8X8_TYPELESS:
318     case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
319         // Swap Red (R) and Blue (B) channels (used to convert from DXGI 1.1 BGR formats to DXGI 1.0 RGB)
320         if ( pDestination == pSource )
321         {
322             uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
323             for( size_t count = 0; count < outSize; count += 4 )
324             {
325                 uint32_t t = *dPtr;
326
327                 uint32_t t1 = (t & 0x00ff0000) >> 16;
328                 uint32_t t2 = (t & 0x000000ff) << 16;
329                 uint32_t t3 = (t & 0x0000ff00);
330                 uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (t & 0xFF000000);
331
332                 *(dPtr++) = t1 | t2 | t3 | ta;
333             }
334         }
335         else
336         {
337             const uint32_t * __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
338             uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
339             size_t size = std::min<size_t>( outSize, inSize );
340             for( size_t count = 0; count < size; count += 4 )
341             {
342                 uint32_t t = *(sPtr++);
343
344                 uint32_t t1 = (t & 0x00ff0000) >> 16;
345                 uint32_t t2 = (t & 0x000000ff) << 16;
346                 uint32_t t3 = (t & 0x0000ff00);
347                 uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (t & 0xFF000000);
348
349                 *(dPtr++) = t1 | t2 | t3 | ta;
350             }
351         }
352         return;
353     }
354
355     // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
356     if ( pDestination == pSource )
357         return;
358
359     size_t size = std::min<size_t>( outSize, inSize );
360     memcpy_s( pDestination, outSize, pSource, size );
361 }
362
363
364 //-------------------------------------------------------------------------------------
365 // Converts an image row with optional clearing of alpha value to 1.0
366 // Returns true if supported, false if expansion case not supported
367 //-------------------------------------------------------------------------------------
368 bool _ExpandScanline( LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat,  
369                       LPCVOID pSource, size_t inSize, DXGI_FORMAT inFormat, DWORD flags )
370 {
371     assert( pDestination && outSize > 0 );
372     assert( pSource && inSize > 0 );
373     assert( IsValid(outFormat) && !IsVideo(outFormat) );
374     assert( IsValid(inFormat) && !IsVideo(inFormat) );
375
376     switch( inFormat )
377     {
378     case DXGI_FORMAT_B5G6R5_UNORM:
379         if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
380             return false;
381
382         // DXGI_FORMAT_B5G6R5_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
383         {
384             const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
385             uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
386
387             for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
388             {
389                 uint16_t t = *(sPtr++);
390
391                 uint32_t t1 = ((t & 0xf800) >> 8) | ((t & 0xe000) >> 13);
392                 uint32_t t2 = ((t & 0x07e0) << 5) | ((t & 0x0600) >> 5);
393                 uint32_t t3 = ((t & 0x001f) << 19) | ((t & 0x001c) << 14);
394
395                 *(dPtr++) = t1 | t2 | t3 | 0xff000000;
396             }
397         }
398         return true;
399         
400     case DXGI_FORMAT_B5G5R5A1_UNORM:
401         if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
402             return false;
403
404         // DXGI_FORMAT_B5G5R5A1_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
405         {
406             const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
407             uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
408
409             for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
410             {
411                 uint16_t t = *(sPtr++);
412
413                 uint32_t t1 = ((t & 0x7c00) >> 7) | ((t & 0x7000) >> 12);
414                 uint32_t t2 = ((t & 0x03e0) << 6) | ((t & 0x0380) << 1);
415                 uint32_t t3 = ((t & 0x001f) << 19) | ((t & 0x001c) << 14);
416                 uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : ((t & 0x8000) ? 0xff000000 : 0);
417
418                 *(dPtr++) = t1 | t2 | t3 | ta;
419             }
420         }
421         return true;
422
423 #ifdef DXGI_1_2_FORMATS
424     case DXGI_FORMAT_B4G4R4A4_UNORM:
425         if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
426             return false;
427
428         // DXGI_FORMAT_B4G4R4A4_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
429         {
430             const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
431             uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
432
433             for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
434             {
435                 uint16_t t = *(sPtr++);
436
437                 uint32_t t1 = ((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8);
438                 uint32_t t2 = ((t & 0x00f0) << 8) | ((t & 0x00f0) << 4);
439                 uint32_t t3 = ((t & 0x000f) << 20) | ((t & 0x000f) << 16);
440                 uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (((t & 0xf000) << 16) | ((t & 0xf000) << 12));
441
442                 *(dPtr++) = t1 | t2 | t3 | ta;
443             }
444         }
445         return true;
446 #endif // DXGI_1_2_FORMATS
447     }
448
449     return false;
450 }
451
452
453 //-------------------------------------------------------------------------------------
454 // Loads an image row into standard RGBA XMVECTOR (aligned) array
455 //-------------------------------------------------------------------------------------
456 #define LOAD_SCANLINE( type, func )\
457         if ( size >= sizeof(type) )\
458         {\
459             const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
460             for( size_t icount = 0; icount < size; icount += sizeof(type) )\
461             {\
462                 if ( dPtr >= ePtr ) break;\
463                 *(dPtr++) = func( sPtr++ );\
464             }\
465             return true;\
466         }\
467         return false;
468
469 #define LOAD_SCANLINE3( type, func, defvec )\
470         if ( size >= sizeof(type) )\
471         {\
472             const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
473             for( size_t icount = 0; icount < size; icount += sizeof(type) )\
474             {\
475                 XMVECTOR v = func( sPtr++ );\
476                 if ( dPtr >= ePtr ) break;\
477                 *(dPtr++) = XMVectorSelect( defvec, v, g_XMSelect1110 );\
478             }\
479             return true;\
480         }\
481         return false;
482
483 #define LOAD_SCANLINE2( type, func, defvec )\
484         if ( size >= sizeof(type) )\
485         {\
486             const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
487             for( size_t icount = 0; icount < size; icount += sizeof(type) )\
488             {\
489                 XMVECTOR v = func( sPtr++ );\
490                 if ( dPtr >= ePtr ) break;\
491                 *(dPtr++) = XMVectorSelect( defvec, v, g_XMSelect1100 );\
492             }\
493             return true;\
494         }\
495         return false;
496
497 bool _LoadScanline( XMVECTOR* pDestination, size_t count,
498                     LPCVOID pSource, size_t size, DXGI_FORMAT format )
499 {
500 #if !defined(_XM_NO_INTRINSICS_)
501     assert( pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0) );
502 #endif
503     assert( pSource && size > 0 );
504     assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
505
506     XMVECTOR* __restrict dPtr = pDestination;
507     if ( !dPtr )
508         return false;
509
510     const XMVECTOR* ePtr = pDestination + count;
511
512     switch( format )
513     {
514     case DXGI_FORMAT_R32G32B32A32_FLOAT:
515         {
516             size_t msize = (size > (sizeof(XMVECTOR)*count)) ? (sizeof(XMVECTOR)*count) : size;
517             memcpy_s( dPtr, sizeof(XMVECTOR)*count, pSource, msize );
518         }
519         return true;
520
521     case DXGI_FORMAT_R32G32B32A32_UINT:
522         LOAD_SCANLINE( XMUINT4, XMLoadUInt4 )
523
524     case DXGI_FORMAT_R32G32B32A32_SINT:
525         LOAD_SCANLINE( XMINT4, XMLoadSInt4 )
526
527     case DXGI_FORMAT_R32G32B32_FLOAT:
528         LOAD_SCANLINE3( XMFLOAT3, XMLoadFloat3, g_XMIdentityR3 )
529
530     case DXGI_FORMAT_R32G32B32_UINT:
531         LOAD_SCANLINE3( XMUINT3, XMLoadUInt3, g_XMIdentityR3 )
532
533     case DXGI_FORMAT_R32G32B32_SINT:
534         LOAD_SCANLINE3( XMINT3, XMLoadSInt3, g_XMIdentityR3 )
535
536     case DXGI_FORMAT_R16G16B16A16_FLOAT:
537         LOAD_SCANLINE( XMHALF4, XMLoadHalf4 )
538
539     case DXGI_FORMAT_R16G16B16A16_UNORM:
540         LOAD_SCANLINE( XMUSHORTN4, XMLoadUShortN4 ) 
541
542     case DXGI_FORMAT_R16G16B16A16_UINT:
543         LOAD_SCANLINE( XMUSHORT4, XMLoadUShort4 )
544
545     case DXGI_FORMAT_R16G16B16A16_SNORM:
546         LOAD_SCANLINE( XMSHORTN4, XMLoadShortN4 )
547
548     case DXGI_FORMAT_R16G16B16A16_SINT:
549         LOAD_SCANLINE( XMSHORT4, XMLoadShort4 )
550
551     case DXGI_FORMAT_R32G32_FLOAT:
552         LOAD_SCANLINE2( XMFLOAT2, XMLoadFloat2, g_XMIdentityR3 )
553
554     case DXGI_FORMAT_R32G32_UINT:
555         LOAD_SCANLINE2( XMUINT2, XMLoadUInt2, g_XMIdentityR3 )
556
557     case DXGI_FORMAT_R32G32_SINT:
558         LOAD_SCANLINE2( XMINT2, XMLoadSInt2, g_XMIdentityR3 )
559
560     case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
561         if ( size >= (sizeof(float)+sizeof(uint32_t)) )
562         {
563             const float * sPtr = reinterpret_cast<const float*>(pSource);
564             for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
565             {
566                 const uint8_t* ps8 = reinterpret_cast<const uint8_t*>( &sPtr[1] );
567                 if ( dPtr >= ePtr ) break;
568                 *(dPtr++) = XMVectorSet( sPtr[0], static_cast<float>( *ps8 ), 0.f, 1.f );
569                 sPtr += 2;
570             }
571             return true;
572         }
573         return false;
574
575     case DXGI_FORMAT_R10G10B10A2_UNORM:
576     case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
577         LOAD_SCANLINE( XMUDECN4, XMLoadUDecN4 );
578
579     case DXGI_FORMAT_R10G10B10A2_UINT:
580         LOAD_SCANLINE( XMUDEC4, XMLoadUDec4 );
581
582     case DXGI_FORMAT_R11G11B10_FLOAT:
583         LOAD_SCANLINE3( XMFLOAT3PK, XMLoadFloat3PK, g_XMIdentityR3 );
584
585     case DXGI_FORMAT_R8G8B8A8_UNORM:
586     case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
587         LOAD_SCANLINE( XMUBYTEN4, XMLoadUByteN4 )
588
589     case DXGI_FORMAT_R8G8B8A8_UINT:
590         LOAD_SCANLINE( XMUBYTE4, XMLoadUByte4 )
591
592     case DXGI_FORMAT_R8G8B8A8_SNORM:
593         LOAD_SCANLINE( XMBYTEN4, XMLoadByteN4 )
594
595     case DXGI_FORMAT_R8G8B8A8_SINT:
596         LOAD_SCANLINE( XMBYTE4, XMLoadByte4 )
597
598     case DXGI_FORMAT_R16G16_FLOAT:
599         LOAD_SCANLINE2( XMHALF2, XMLoadHalf2, g_XMIdentityR3 )
600
601     case DXGI_FORMAT_R16G16_UNORM:
602         LOAD_SCANLINE2( XMUSHORTN2, XMLoadUShortN2, g_XMIdentityR3 )
603
604     case DXGI_FORMAT_R16G16_UINT:
605         LOAD_SCANLINE2( XMUSHORT2, XMLoadUShort2, g_XMIdentityR3 )
606
607     case DXGI_FORMAT_R16G16_SNORM:
608         LOAD_SCANLINE2( XMSHORTN2, XMLoadShortN2, g_XMIdentityR3 )
609
610     case DXGI_FORMAT_R16G16_SINT:
611         LOAD_SCANLINE2( XMSHORT2, XMLoadShort2, g_XMIdentityR3 )
612
613     case DXGI_FORMAT_D32_FLOAT:
614     case DXGI_FORMAT_R32_FLOAT:
615         if ( size >= sizeof(float) )
616         {
617             const float* __restrict sPtr = reinterpret_cast<const float*>(pSource);
618             for( size_t icount = 0; icount < size; icount += sizeof(float) )
619             {
620                 XMVECTOR v = XMLoadFloat( sPtr++ );
621                 if ( dPtr >= ePtr ) break;
622                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
623             }
624             return true;
625         }
626         return false;
627
628     case DXGI_FORMAT_R32_UINT:
629         if ( size >= sizeof(uint32_t) )
630         {
631             const uint32_t* __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
632             for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
633             {
634                 XMVECTOR v = XMLoadInt( sPtr++ );
635                 v = XMConvertVectorUIntToFloat( v, 0 );
636                 if ( dPtr >= ePtr ) break;
637                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
638             }
639             return true;
640         }
641         return false;
642
643     case DXGI_FORMAT_R32_SINT:
644         if ( size >= sizeof(int32_t) )
645         {
646             const int32_t * __restrict sPtr = reinterpret_cast<const int32_t*>(pSource);
647             for( size_t icount = 0; icount < size; icount += sizeof(int32_t) )
648             {
649                 XMVECTOR v = XMLoadInt( reinterpret_cast<const uint32_t*> (sPtr++) );
650                 v = XMConvertVectorIntToFloat( v, 0 );
651                 if ( dPtr >= ePtr ) break;
652                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
653             }
654             return true;
655         }
656         return false;
657
658     case DXGI_FORMAT_D24_UNORM_S8_UINT:
659         if ( size >= sizeof(uint32_t) )
660         {
661             const uint32_t * sPtr = reinterpret_cast<const uint32_t*>(pSource);
662             for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
663             {
664                 float d = static_cast<float>( *sPtr & 0xFFFFFF ) / 16777215.f;
665                 float s = static_cast<float>( ( *sPtr & 0xFF000000 ) >> 24 );
666                 ++sPtr;
667                 if ( dPtr >= ePtr ) break;
668                 *(dPtr++) = XMVectorSet( d, s, 0.f, 1.f );
669             }
670             return true;
671         }
672         return false;
673
674     case DXGI_FORMAT_R8G8_UNORM:
675         LOAD_SCANLINE2( XMUBYTEN2, XMLoadUByteN2, g_XMIdentityR3 )
676
677     case DXGI_FORMAT_R8G8_UINT:
678         LOAD_SCANLINE2( XMUBYTE2, XMLoadUByte2, g_XMIdentityR3 )
679
680     case DXGI_FORMAT_R8G8_SNORM:
681         LOAD_SCANLINE2( XMBYTEN2, XMLoadByteN2, g_XMIdentityR3 )
682
683     case DXGI_FORMAT_R8G8_SINT:
684         LOAD_SCANLINE2( XMBYTE2, XMLoadByte2, g_XMIdentityR3 )
685
686     case DXGI_FORMAT_R16_FLOAT:
687         if ( size >= sizeof(HALF) )
688         {
689             const HALF * __restrict sPtr = reinterpret_cast<const HALF*>(pSource);
690             for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
691             {
692                 if ( dPtr >= ePtr ) break;
693                 *(dPtr++) = XMVectorSet( XMConvertHalfToFloat(*sPtr++), 0.f, 0.f, 1.f );
694             }
695             return true;
696         }
697         return false;
698
699     case DXGI_FORMAT_D16_UNORM:
700     case DXGI_FORMAT_R16_UNORM:
701         if ( size >= sizeof(uint16_t) )
702         {
703             const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
704             for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
705             {
706                 if ( dPtr >= ePtr ) break;
707                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 65535.f, 0.f, 0.f, 1.f );
708             }
709             return true;
710         }
711         return false;
712
713     case DXGI_FORMAT_R16_UINT:
714         if ( size >= sizeof(uint16_t) )
715         {
716             const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
717             for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
718             {
719                 if ( dPtr >= ePtr ) break;
720                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
721             }
722             return true;
723         }
724         return false;
725
726     case DXGI_FORMAT_R16_SNORM:
727         if ( size >= sizeof(int16_t) )
728         {
729             const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
730             for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
731             {
732                 if ( dPtr >= ePtr ) break;
733                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 32767.f, 0.f, 0.f, 1.f );
734             }
735             return true;
736         }
737         return false;
738
739     case DXGI_FORMAT_R16_SINT:
740         if ( size >= sizeof(int16_t) )
741         {
742             const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
743             for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
744             {
745                 if ( dPtr >= ePtr ) break;
746                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
747             }
748             return true;
749         }
750         return false;
751
752     case DXGI_FORMAT_R8_UNORM:
753         if ( size >= sizeof(uint8_t) )
754         {
755             const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
756             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
757             {
758                 if ( dPtr >= ePtr ) break;
759                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 255.f, 0.f, 0.f, 1.f );
760             }
761             return true;
762         }
763         return false;
764
765     case DXGI_FORMAT_R8_UINT:
766         if ( size >= sizeof(uint8_t) )
767         {
768             const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
769             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
770             {
771                 if ( dPtr >= ePtr ) break;
772                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
773             }
774             return true;
775         }
776         return false;
777
778     case DXGI_FORMAT_R8_SNORM:
779         if ( size >= sizeof(char) )
780         {
781             const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
782             for( size_t icount = 0; icount < size; icount += sizeof(char) )
783             {
784                 if ( dPtr >= ePtr ) break;
785                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 127.f, 0.f, 0.f, 1.f );
786             }
787             return true;
788         }
789         return false;
790
791     case DXGI_FORMAT_R8_SINT:
792         if ( size >= sizeof(char) )
793         {
794             const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
795             for( size_t icount = 0; icount < size; icount += sizeof(char) )
796             {
797                 if ( dPtr >= ePtr ) break;
798                 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
799             }
800             return true;
801         }
802         return false;
803
804     case DXGI_FORMAT_A8_UNORM:
805         if ( size >= sizeof(uint8_t) )
806         {
807             const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
808             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
809             {
810                 if ( dPtr >= ePtr ) break;
811                 *(dPtr++) = XMVectorSet( 0.f, 0.f, 0.f, static_cast<float>(*sPtr++) / 255.f );
812             }
813             return true;
814         }
815         return false;
816
817     case DXGI_FORMAT_R1_UNORM:
818         if ( size >= sizeof(uint8_t) )
819         {
820             const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
821             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
822             {
823                 for( size_t bcount = 0; bcount < 8; ++bcount )
824                 {
825                     if ( dPtr >= ePtr ) break;
826                     *(dPtr++) = XMVectorSet( (((*sPtr >> bcount) & 0x1) ? 1.f : 0.f), 0.f, 0.f, 1.f );
827                 }
828                 
829                 ++sPtr;
830             }
831             return true;
832         }
833         return false;
834
835     case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
836         LOAD_SCANLINE3( XMFLOAT3SE, XMLoadFloat3SE, g_XMIdentityR3 )
837
838     case DXGI_FORMAT_R8G8_B8G8_UNORM:
839         if ( size >= sizeof(XMUBYTEN4) )
840         {
841             const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
842             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
843             {
844                 XMVECTOR v = XMLoadUByteN4( sPtr++ );
845                 XMVECTOR v1 = XMVectorSwizzle<0, 3, 2, 1>( v );
846                 if ( dPtr >= ePtr ) break;
847                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1110 );
848                 if ( dPtr >= ePtr ) break;
849                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v1, g_XMSelect1110 );
850             }
851             return true;
852         }
853         return false;
854
855     case DXGI_FORMAT_G8R8_G8B8_UNORM:
856         if ( size >= sizeof(XMUBYTEN4) )
857         {
858             const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
859             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
860             {
861                 XMVECTOR v = XMLoadUByteN4( sPtr++ );
862                 XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>( v );
863                 XMVECTOR v1 = XMVectorSwizzle<1, 2, 3, 0>( v );
864                 if ( dPtr >= ePtr ) break;
865                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v0, g_XMSelect1110 );
866                 if ( dPtr >= ePtr ) break;
867                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v1, g_XMSelect1110 );
868             }
869             return true;
870         }
871         return false;
872
873     case DXGI_FORMAT_B5G6R5_UNORM:
874         if ( size >= sizeof(XMU565) )
875         {
876             static XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/63.f, 1.f/31.f, 1.f };
877             const XMU565 * __restrict sPtr = reinterpret_cast<const XMU565*>(pSource);
878             for( size_t icount = 0; icount < size; icount += sizeof(XMU565) )
879             {
880                 XMVECTOR v = XMLoadU565( sPtr++ );
881                 v = XMVectorMultiply( v, s_Scale );
882                 v = XMVectorSwizzle<2, 1, 0, 3>( v );
883                 if ( dPtr >= ePtr ) break;
884                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1110 );
885             }
886             return true;
887         }
888         return false;
889
890     case DXGI_FORMAT_B5G5R5A1_UNORM:
891         if ( size >= sizeof(XMU555) )
892         {
893             static XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/31.f, 1.f/31.f, 1.f };
894             const XMU555 * __restrict sPtr = reinterpret_cast<const XMU555*>(pSource);
895             for( size_t icount = 0; icount < size; icount += sizeof(XMU555) )
896             {
897                 XMVECTOR v = XMLoadU555( sPtr++ );
898                 v = XMVectorMultiply( v, s_Scale );
899                 if ( dPtr >= ePtr ) break;
900                 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
901             }
902             return true;
903         }
904         return false;
905
906     case DXGI_FORMAT_B8G8R8A8_UNORM:
907     case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
908         if ( size >= sizeof(XMUBYTEN4) )
909         {
910             const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
911             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
912             {
913                 XMVECTOR v = XMLoadUByteN4( sPtr++ );
914                 if ( dPtr >= ePtr ) break;
915                 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
916             }
917             return true;
918         }
919         return false;
920
921     case DXGI_FORMAT_B8G8R8X8_UNORM:
922     case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
923         if ( size >= sizeof(XMUBYTEN4) )
924         {
925             const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
926             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
927             {
928                 XMVECTOR v = XMLoadUByteN4( sPtr++ );
929                 v = XMVectorSwizzle<2, 1, 0, 3>( v );
930                 if ( dPtr >= ePtr ) break;
931                 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1110 );
932             }
933             return true;
934         }
935         return false;
936
937 #ifdef DXGI_1_2_FORMATS
938     case DXGI_FORMAT_B4G4R4A4_UNORM:
939         if ( size >= sizeof(XMUNIBBLE4) )
940         {
941             static XMVECTORF32 s_Scale = { 1.f/15.f, 1.f/15.f, 1.f/15.f, 1.f/15.f };
942             const XMUNIBBLE4 * __restrict sPtr = reinterpret_cast<const XMUNIBBLE4*>(pSource);
943             for( size_t icount = 0; icount < size; icount += sizeof(XMUNIBBLE4) )
944             {
945                 XMVECTOR v = XMLoadUNibble4( sPtr++ );
946                 v = XMVectorMultiply( v, s_Scale );
947                 if ( dPtr >= ePtr ) break;
948                 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
949             }
950             return true;
951         }
952         return false;
953
954     // we don't support the video formats ( see IsVideo function )
955 #endif // DXGI_1_2_FORMATS
956
957     default:
958         return false;
959     }
960 }
961
962
963 //-------------------------------------------------------------------------------------
964 // Stores an image row from standard RGBA XMVECTOR (aligned) array
965 //-------------------------------------------------------------------------------------
966 #define STORE_SCANLINE( type, func )\
967         if ( size >= sizeof(type) )\
968         {\
969             type * __restrict dPtr = reinterpret_cast<type*>(pDestination);\
970             for( size_t icount = 0; icount < size; icount += sizeof(type) )\
971             {\
972                 if ( sPtr >= ePtr ) break;\
973                 func( dPtr++, *sPtr++ );\
974             }\
975         }\
976         return true;
977
978 bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
979                      const XMVECTOR* pSource, size_t count )
980 {
981     assert( pDestination && size > 0 );
982 #if !defined(_XM_NO_INTRINSICS_)
983     assert( pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0) );
984 #endif
985     assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
986
987     const XMVECTOR* __restrict sPtr = pSource;
988     if ( !sPtr )
989         return false;
990
991     const XMVECTOR* ePtr = pSource + count;
992
993     switch( format )
994     {
995     case DXGI_FORMAT_R32G32B32A32_FLOAT:
996         STORE_SCANLINE( XMFLOAT4, XMStoreFloat4 )
997
998     case DXGI_FORMAT_R32G32B32A32_UINT:
999         STORE_SCANLINE( XMUINT4, XMStoreUInt4 )
1000
1001     case DXGI_FORMAT_R32G32B32A32_SINT:
1002         STORE_SCANLINE( XMINT4, XMStoreSInt4 )
1003
1004     case DXGI_FORMAT_R32G32B32_FLOAT:
1005         STORE_SCANLINE( XMFLOAT3, XMStoreFloat3 )
1006
1007     case DXGI_FORMAT_R32G32B32_UINT:
1008         STORE_SCANLINE( XMUINT3, XMStoreUInt3 )
1009
1010     case DXGI_FORMAT_R32G32B32_SINT:
1011         STORE_SCANLINE( XMINT3, XMStoreSInt3 )
1012
1013     case DXGI_FORMAT_R16G16B16A16_FLOAT:
1014         STORE_SCANLINE( XMHALF4, XMStoreHalf4 )
1015
1016     case DXGI_FORMAT_R16G16B16A16_UNORM:
1017         STORE_SCANLINE( XMUSHORTN4, XMStoreUShortN4 ) 
1018
1019     case DXGI_FORMAT_R16G16B16A16_UINT:
1020         STORE_SCANLINE( XMUSHORT4, XMStoreUShort4 )
1021
1022     case DXGI_FORMAT_R16G16B16A16_SNORM:
1023         STORE_SCANLINE( XMSHORTN4, XMStoreShortN4 )
1024
1025     case DXGI_FORMAT_R16G16B16A16_SINT:
1026         STORE_SCANLINE( XMSHORT4, XMStoreShort4 )
1027
1028     case DXGI_FORMAT_R32G32_FLOAT:
1029         STORE_SCANLINE( XMFLOAT2, XMStoreFloat2 )
1030
1031     case DXGI_FORMAT_R32G32_UINT:
1032         STORE_SCANLINE( XMUINT2, XMStoreUInt2 )
1033
1034     case DXGI_FORMAT_R32G32_SINT:
1035         STORE_SCANLINE( XMINT2, XMStoreSInt2 )
1036
1037     case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
1038         if ( size >= (sizeof(float)+sizeof(uint32_t)) )
1039         {
1040             float *dPtr = reinterpret_cast<float*>(pDestination);
1041             for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
1042             {
1043                 if ( sPtr >= ePtr ) break;
1044                 XMFLOAT4 f;
1045                 XMStoreFloat4( &f, *sPtr++ );
1046                 dPtr[0] = f.x;
1047                 uint8_t* ps8 = reinterpret_cast<uint8_t*>( &dPtr[1] );
1048                 ps8[0] = static_cast<uint8_t>( std::min<float>( 255.f, std::max<float>( 0.f, f.y ) ) );
1049                 ps8[1] = ps8[2] = ps8[3] = 0;
1050                 dPtr += 2;
1051             }
1052         }
1053         return true;
1054
1055     case DXGI_FORMAT_R10G10B10A2_UNORM:
1056     case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
1057         STORE_SCANLINE( XMUDECN4, XMStoreUDecN4 );
1058
1059     case DXGI_FORMAT_R10G10B10A2_UINT:
1060         STORE_SCANLINE( XMUDEC4, XMStoreUDec4 );
1061
1062     case DXGI_FORMAT_R11G11B10_FLOAT:
1063         STORE_SCANLINE( XMFLOAT3PK, XMStoreFloat3PK );
1064
1065     case DXGI_FORMAT_R8G8B8A8_UNORM:
1066     case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1067         STORE_SCANLINE( XMUBYTEN4, XMStoreUByteN4 )
1068
1069     case DXGI_FORMAT_R8G8B8A8_UINT:
1070         STORE_SCANLINE( XMUBYTE4, XMStoreUByte4 )
1071
1072     case DXGI_FORMAT_R8G8B8A8_SNORM:
1073         STORE_SCANLINE( XMBYTEN4, XMStoreByteN4 )
1074
1075     case DXGI_FORMAT_R8G8B8A8_SINT:
1076         STORE_SCANLINE( XMBYTE4, XMStoreByte4 )
1077
1078     case DXGI_FORMAT_R16G16_FLOAT:
1079         STORE_SCANLINE( XMHALF2, XMStoreHalf2 )
1080
1081     case DXGI_FORMAT_R16G16_UNORM:
1082         STORE_SCANLINE( XMUSHORTN2, XMStoreUShortN2 )
1083
1084     case DXGI_FORMAT_R16G16_UINT:
1085         STORE_SCANLINE( XMUSHORT2, XMStoreUShort2 )
1086
1087     case DXGI_FORMAT_R16G16_SNORM:
1088         STORE_SCANLINE( XMSHORTN2, XMStoreShortN2 )
1089
1090     case DXGI_FORMAT_R16G16_SINT:
1091         STORE_SCANLINE( XMSHORT2, XMStoreShort2 )
1092
1093     case DXGI_FORMAT_D32_FLOAT:
1094     case DXGI_FORMAT_R32_FLOAT:
1095         if ( size >= sizeof(float) )
1096         {
1097             float * __restrict dPtr = reinterpret_cast<float*>(pDestination);
1098             for( size_t icount = 0; icount < size; icount += sizeof(float) )
1099             {
1100                 if ( sPtr >= ePtr ) break;
1101                 XMStoreFloat( dPtr++, *(sPtr++) );
1102             }
1103         }
1104         return true;
1105
1106     case DXGI_FORMAT_R32_UINT:
1107         if ( size >= sizeof(uint32_t) )
1108         {
1109             uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
1110             for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1111             {
1112                 if ( sPtr >= ePtr ) break;
1113                 XMVECTOR v = XMConvertVectorFloatToUInt( *(sPtr++), 0 );
1114                 XMStoreInt( dPtr++, v );
1115             }
1116         }
1117         return true;
1118
1119     case DXGI_FORMAT_R32_SINT:
1120         if ( size >= sizeof(uint32_t) )
1121         {
1122             uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
1123             for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1124             {
1125                 if ( sPtr >= ePtr ) break;
1126                 XMVECTOR v = XMConvertVectorFloatToInt( *(sPtr++), 0 );
1127                 XMStoreInt( dPtr++, v );
1128             }
1129         }
1130         return true;
1131
1132     case DXGI_FORMAT_D24_UNORM_S8_UINT:
1133         if ( size >= sizeof(uint32_t) )
1134         {
1135             static const XMVECTORF32 clamp = { 1.f, 255.f, 0.f, 0.f };
1136             XMVECTOR zero = XMVectorZero();
1137             uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
1138             for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1139             {
1140                 if ( sPtr >= ePtr ) break;
1141                 XMFLOAT4 f;
1142                 XMStoreFloat4( &f, XMVectorClamp( *sPtr++, zero, clamp ) );
1143                 *dPtr++ = (static_cast<uint32_t>( f.x * 16777215.f ) & 0xFFFFFF)
1144                           | ((static_cast<uint32_t>( f.y ) & 0xFF) << 24);
1145             }
1146         }
1147         return true;
1148
1149     case DXGI_FORMAT_R8G8_UNORM:
1150         STORE_SCANLINE( XMUBYTEN2, XMStoreUByteN2 )
1151
1152     case DXGI_FORMAT_R8G8_UINT:
1153         STORE_SCANLINE( XMUBYTE2, XMStoreUByte2 )
1154
1155     case DXGI_FORMAT_R8G8_SNORM:
1156         STORE_SCANLINE( XMBYTEN2, XMStoreByteN2 )
1157
1158     case DXGI_FORMAT_R8G8_SINT:
1159         STORE_SCANLINE( XMBYTE2, XMStoreByte2 )
1160
1161     case DXGI_FORMAT_R16_FLOAT:
1162         if ( size >= sizeof(HALF) )
1163         {
1164             HALF * __restrict dPtr = reinterpret_cast<HALF*>(pDestination);
1165             for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
1166             {
1167                 if ( sPtr >= ePtr ) break;
1168                 float v = XMVectorGetX( *sPtr++ );
1169                 *(dPtr++) = XMConvertFloatToHalf(v);
1170             }
1171         }
1172         return true;
1173
1174     case DXGI_FORMAT_D16_UNORM:
1175     case DXGI_FORMAT_R16_UNORM:
1176         if ( size >= sizeof(int16_t) )
1177         {
1178             int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1179             for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
1180             {
1181                 if ( sPtr >= ePtr ) break;
1182                 float v = XMVectorGetX( *sPtr++ );
1183                 v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
1184                 *(dPtr++) = static_cast<uint16_t>( v*65535.f + 0.5f );
1185             }
1186         }
1187         return true;
1188
1189     case DXGI_FORMAT_R16_UINT:
1190         if ( size >= sizeof(uint16_t) )
1191         {
1192             uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
1193             for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
1194             {
1195                 if ( sPtr >= ePtr ) break;
1196                 float v = XMVectorGetX( *sPtr++ );
1197                 v = std::max<float>( std::min<float>( v, 65535.f ), 0.f );
1198                 *(dPtr++) = static_cast<uint16_t>(v);
1199             }
1200         }
1201         return true;
1202
1203     case DXGI_FORMAT_R16_SNORM:
1204         if ( size >= sizeof(int16_t) )
1205         {
1206             int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1207             for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
1208             {
1209                 if ( sPtr >= ePtr ) break;
1210                 float v = XMVectorGetX( *sPtr++ );
1211                 v = std::max<float>( std::min<float>( v, 1.f ), -1.f );
1212                 *(dPtr++) = static_cast<uint16_t>( v * 32767.f );
1213             }
1214         }
1215         return true;
1216
1217     case DXGI_FORMAT_R16_SINT:
1218         if ( size >= sizeof(int16_t) )
1219         {
1220             int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1221             for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
1222             {
1223                 if ( sPtr >= ePtr ) break;
1224                 float v = XMVectorGetX( *sPtr++ );
1225                 v = std::max<float>( std::min<float>( v, 32767.f ), -32767.f );
1226                 *(dPtr++) = static_cast<int16_t>(v);
1227             }
1228         }
1229         return true;
1230
1231     case DXGI_FORMAT_R8_UNORM:
1232         if ( size >= sizeof(uint8_t) )
1233         {
1234             uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1235             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1236             {
1237                 if ( sPtr >= ePtr ) break;
1238                 float v = XMVectorGetX( *sPtr++ );
1239                 v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
1240                 *(dPtr++) = static_cast<uint8_t>( v * 255.f);
1241             }
1242         }
1243         return true;
1244
1245     case DXGI_FORMAT_R8_UINT:
1246         if ( size >= sizeof(uint8_t) )
1247         {
1248             uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1249             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1250             {
1251                 if ( sPtr >= ePtr ) break;
1252                 float v = XMVectorGetX( *sPtr++ );
1253                 v = std::max<float>( std::min<float>( v, 255.f ), 0.f );
1254                 *(dPtr++) = static_cast<uint8_t>(v);
1255             }
1256         }
1257         return true;
1258
1259     case DXGI_FORMAT_R8_SNORM:
1260         if ( size >= sizeof(char) )
1261         {
1262             char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
1263             for( size_t icount = 0; icount < size; icount += sizeof(char) )
1264             {
1265                 if ( sPtr >= ePtr ) break;
1266                 float v = XMVectorGetX( *sPtr++ );
1267                 v = std::max<float>( std::min<float>( v, 1.f ), -1.f );
1268                 *(dPtr++) = static_cast<char>( v * 127.f );
1269             }
1270         }
1271         return true;
1272
1273     case DXGI_FORMAT_R8_SINT:
1274         if ( size >= sizeof(char) )
1275         {
1276             char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
1277             for( size_t icount = 0; icount < size; icount += sizeof(char) )
1278             {
1279                 if ( sPtr >= ePtr ) break;
1280                 float v = XMVectorGetX( *sPtr++ );
1281                 v = std::max<float>( std::min<float>( v, 127.f ), -127.f );
1282                 *(dPtr++) = static_cast<char>( v );
1283             }
1284         }
1285         return true;
1286
1287     case DXGI_FORMAT_A8_UNORM:
1288         if ( size >= sizeof(uint8_t) )
1289         {
1290             uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1291             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1292             {
1293                 if ( sPtr >= ePtr ) break;
1294                 float v = XMVectorGetW( *sPtr++ );
1295                 v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
1296                 *(dPtr++) = static_cast<uint8_t>( v * 255.f);
1297             }
1298         }
1299         return true;
1300
1301     case DXGI_FORMAT_R1_UNORM:
1302         if ( size >= sizeof(uint8_t) )
1303         {
1304             uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1305             for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1306             {
1307                 uint8_t pixels = 0;
1308                 for( size_t bcount = 0; bcount < 8; ++bcount )
1309                 {
1310                     if ( sPtr >= ePtr ) break;
1311                     float v = XMVectorGetX( *sPtr++ );
1312                     if ( v > 0.5f )
1313                         pixels |= 1 << bcount;
1314                 }
1315                 *(dPtr++) = pixels;
1316             }
1317         }
1318         return true;
1319
1320     case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
1321         STORE_SCANLINE( XMFLOAT3SE, XMStoreFloat3SE )
1322
1323     case DXGI_FORMAT_R8G8_B8G8_UNORM:
1324         if ( size >= sizeof(XMUBYTEN4) )
1325         {
1326             XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1327             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1328             {
1329                 if ( sPtr >= ePtr ) break;
1330                 XMVECTOR v0 = *sPtr++;
1331                 XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY( *sPtr++ ) : XMVectorZero();
1332                 XMVECTOR v = XMVectorSelect( v1, v0, g_XMSelect1110 );
1333                 XMStoreUByteN4( dPtr++, v );
1334             }
1335         }
1336         return true;
1337
1338     case DXGI_FORMAT_G8R8_G8B8_UNORM:
1339         if ( size >= sizeof(XMUBYTEN4) )
1340         {
1341             static XMVECTORI32 select1101 = {XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1};
1342
1343             XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1344             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1345             {
1346                 if ( sPtr >= ePtr ) break;
1347                 XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>( *sPtr++ );
1348                 XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY( *sPtr++ ) : XMVectorZero();
1349                 XMVECTOR v = XMVectorSelect( v1, v0, select1101 );
1350                 XMStoreUByteN4( dPtr++, v );
1351             }
1352         }
1353         return true;
1354
1355     case DXGI_FORMAT_B5G6R5_UNORM:
1356         if ( size >= sizeof(XMU565) )
1357         {
1358             static XMVECTORF32 s_Scale = { 31.f, 63.f, 31.f, 1.f };
1359             XMU565 * __restrict dPtr = reinterpret_cast<XMU565*>(pDestination);
1360             for( size_t icount = 0; icount < size; icount += sizeof(XMU565) )
1361             {
1362                 if ( sPtr >= ePtr ) break;
1363                 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1364                 v = XMVectorMultiply( v, s_Scale );
1365                 XMStoreU565( dPtr++, v );
1366             }
1367         }
1368         return true;
1369
1370     case DXGI_FORMAT_B5G5R5A1_UNORM:
1371         if ( size >= sizeof(XMU555) )
1372         {
1373             static XMVECTORF32 s_Scale = { 31.f, 31.f, 31.f, 1.f };
1374             XMU555 * __restrict dPtr = reinterpret_cast<XMU555*>(pDestination);
1375             for( size_t icount = 0; icount < size; icount += sizeof(XMU555) )
1376             {
1377                 if ( sPtr >= ePtr ) break;
1378                 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1379                 v = XMVectorMultiply( v, s_Scale );
1380                 XMStoreU555( dPtr++, v );
1381             }
1382         }
1383         return true;
1384
1385     case DXGI_FORMAT_B8G8R8A8_UNORM:
1386     case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1387         if ( size >= sizeof(XMUBYTEN4) )
1388         {
1389             XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1390             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1391             {
1392                 if ( sPtr >= ePtr ) break;
1393                 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1394                 XMStoreUByteN4( dPtr++, v );
1395             }
1396         }
1397         return true;
1398
1399     case DXGI_FORMAT_B8G8R8X8_UNORM:
1400     case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
1401         if ( size >= sizeof(XMUBYTEN4) )
1402         {
1403             XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1404             for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1405             {
1406                 if ( sPtr >= ePtr ) break;
1407                 XMVECTOR v = XMVectorPermute<2, 1, 0, 7>( *sPtr++, g_XMIdentityR3 );
1408                 XMStoreUByteN4( dPtr++, v );
1409             }
1410         }
1411         return true;
1412
1413 #ifdef DXGI_1_2_FORMATS
1414     case DXGI_FORMAT_B4G4R4A4_UNORM:
1415         if ( size >= sizeof(XMUNIBBLE4) )
1416         {
1417             static XMVECTORF32 s_Scale = { 15.f, 15.f, 15.f, 15.f };
1418             XMUNIBBLE4 * __restrict dPtr = reinterpret_cast<XMUNIBBLE4*>(pDestination);
1419             for( size_t icount = 0; icount < size; icount += sizeof(XMUNIBBLE4) )
1420             {
1421                 if ( sPtr >= ePtr ) break;
1422                 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1423                 v = XMVectorMultiply( v, s_Scale );
1424                 XMStoreUNibble4( dPtr++, v );
1425             }
1426         }
1427         return true;
1428
1429     // We don't support the video formats ( see IsVideo function )
1430 #endif // DXGI_1_2_FORMATS
1431
1432     default:
1433         return false;
1434     }
1435 }
1436
1437
1438 //-------------------------------------------------------------------------------------
1439 // Convert DXGI image to/from GUID_WICPixelFormat128bppRGBAFloat (no range conversions)
1440 //-------------------------------------------------------------------------------------
1441 HRESULT _ConvertToR32G32B32A32( const Image& srcImage, ScratchImage& image )
1442 {
1443     if ( !srcImage.pixels )
1444         return E_POINTER;
1445
1446     HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
1447     if ( FAILED(hr) )
1448         return hr;
1449
1450     const Image *img = image.GetImage( 0, 0, 0 );
1451     if ( !img )
1452     {
1453         image.Release();
1454         return E_POINTER;
1455     }
1456
1457     uint8_t* pDest = img->pixels;
1458     if ( !pDest )
1459     {
1460         image.Release();
1461         return E_POINTER;
1462     }
1463
1464     const uint8_t *pSrc = srcImage.pixels;
1465     for( size_t h = 0; h < srcImage.height; ++h )
1466     {
1467         if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
1468         {
1469             image.Release();
1470             return E_FAIL;
1471         }
1472
1473         pSrc += srcImage.rowPitch;
1474         pDest += img->rowPitch;
1475     }
1476
1477     return S_OK;
1478 }
1479
1480 HRESULT _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage )
1481 {
1482     assert( srcImage.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1483
1484     if ( !srcImage.pixels || !destImage.pixels )
1485         return E_POINTER;
1486
1487     if ( srcImage.width != destImage.width || srcImage.height != destImage.height )
1488         return E_FAIL;
1489
1490     const uint8_t *pSrc = srcImage.pixels;
1491     uint8_t* pDest = destImage.pixels;
1492
1493     for( size_t h = 0; h < srcImage.height; ++h )
1494     {
1495         if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
1496             return E_FAIL;
1497
1498         pSrc += srcImage.rowPitch;
1499         pDest += destImage.rowPitch;
1500     }
1501
1502     return S_OK;
1503 }
1504
1505 HRESULT _ConvertFromR32G32B32A32( const Image& srcImage, DXGI_FORMAT format, ScratchImage& image )
1506 {
1507     if ( !srcImage.pixels )
1508         return E_POINTER;
1509
1510     HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
1511     if ( FAILED(hr) )
1512         return hr;
1513
1514     const Image *img = image.GetImage( 0, 0, 0 );
1515     if ( !img )
1516     {
1517         image.Release();
1518         return E_POINTER;
1519     }
1520
1521     hr = _ConvertFromR32G32B32A32( srcImage, *img );
1522     if ( FAILED(hr) )
1523     {
1524         image.Release();
1525         return hr;
1526     }
1527
1528     return S_OK;
1529 }
1530
1531 HRESULT _ConvertFromR32G32B32A32( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, ScratchImage& result )
1532 {
1533     if ( !srcImages )
1534         return E_POINTER;
1535
1536     result.Release();
1537
1538     assert( metadata.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1539
1540     TexMetadata mdata2 = metadata;
1541     mdata2.format = format;
1542     HRESULT hr = result.Initialize( mdata2 );
1543     if ( FAILED(hr) )
1544         return hr;
1545
1546     if ( nimages != result.GetImageCount() )
1547     {
1548         result.Release();
1549         return E_FAIL;
1550     }
1551
1552     const Image* dest = result.GetImages();
1553     if ( !dest )
1554     {
1555         result.Release();
1556         return E_POINTER;
1557     }
1558
1559     for( size_t index=0; index < nimages; ++index )
1560     {
1561         const Image& src = srcImages[ index ];
1562         const Image& dst = dest[ index ];
1563
1564         assert( src.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1565         assert( dst.format == format );
1566
1567         if ( src.width != dst.width || src.height != dst.height )
1568         {
1569             result.Release();
1570             return E_FAIL;
1571         }
1572
1573         const uint8_t* pSrc = src.pixels;
1574         uint8_t* pDest = dst.pixels;
1575         if ( !pSrc || !pDest )
1576         {
1577             result.Release();
1578             return E_POINTER;
1579         }
1580
1581         for( size_t h=0; h < src.height; ++h )
1582         {
1583             if ( !_StoreScanline( pDest, dst.rowPitch, format, reinterpret_cast<const XMVECTOR*>(pSrc), src.width ) )
1584             {
1585                 result.Release();
1586                 return E_FAIL;
1587             }
1588
1589             pSrc += src.rowPitch;
1590             pDest += dst.rowPitch;
1591         }
1592     }
1593
1594     return S_OK;
1595 }
1596
1597
1598 //-------------------------------------------------------------------------------------
1599 // RGB -> sRGB
1600 //-------------------------------------------------------------------------------------
1601 static const uint32_t g_fEncodeGamma22[] =
1602 {
1603     0x00000000, 0x3bd56bd3, 0x3c486344, 0x3c90da15, 0x3cbc2677, 0x3ce67704, 0x3d080183, 0x3d1c7728,
1604     0x3d30a8fb, 0x3d44a03c, 0x3d586400, 0x3d6bf9e7, 0x3d7f6679, 0x3d8956bd, 0x3d92e906, 0x3d9c6b70,
1605     0x3da5df22, 0x3daf451b, 0x3db89e3e, 0x3dc1eb50, 0x3dcb2d04, 0x3dd463f7, 0x3ddd90b9, 0x3de6b3ca,
1606     0x3defcda0, 0x3df8dea6, 0x3e00f3a0, 0x3e0573e3, 0x3e09f046, 0x3e0e68f0, 0x3e12de06, 0x3e174fa6,
1607     0x3e1bbdf2, 0x3e202906, 0x3e2490fd, 0x3e28f5f1, 0x3e2d57fb, 0x3e31b72f, 0x3e3613a4, 0x3e3a6d6e,
1608     0x3e3ec4a0, 0x3e43194d, 0x3e476b84, 0x3e4bbb57, 0x3e5008d7, 0x3e54540f, 0x3e589d0f, 0x3e5ce3e5,
1609     0x3e61289d, 0x3e656b44, 0x3e69abe5, 0x3e6dea8d, 0x3e722745, 0x3e766217, 0x3e7a9b0e, 0x3e7ed235,
1610     0x3e8183c9, 0x3e839d98, 0x3e85b68c, 0x3e87cea8, 0x3e89e5f2, 0x3e8bfc6b, 0x3e8e1219, 0x3e9026ff,
1611     0x3e923b20, 0x3e944e7f, 0x3e966120, 0x3e987307, 0x3e9a8436, 0x3e9c94af, 0x3e9ea476, 0x3ea0b38e,
1612     0x3ea2c1fb, 0x3ea4cfbb, 0x3ea6dcd5, 0x3ea8e94a, 0x3eaaf51c, 0x3ead004e, 0x3eaf0ae2, 0x3eb114d9,
1613     0x3eb31e37, 0x3eb526fe, 0x3eb72f2f, 0x3eb936cd, 0x3ebb3dd8, 0x3ebd4454, 0x3ebf4a43, 0x3ec14fa5,
1614     0x3ec3547e, 0x3ec558cd, 0x3ec75c95, 0x3ec95fd8, 0x3ecb6297, 0x3ecd64d4, 0x3ecf6690, 0x3ed167ce,
1615     0x3ed3688e, 0x3ed568d1, 0x3ed76899, 0x3ed967e9, 0x3edb66bf, 0x3edd651f, 0x3edf630a, 0x3ee16080,
1616     0x3ee35d84, 0x3ee55a16, 0x3ee75636, 0x3ee951e8, 0x3eeb4d2a, 0x3eed4800, 0x3eef4269, 0x3ef13c68,
1617     0x3ef335fc, 0x3ef52f26, 0x3ef727ea, 0x3ef92046, 0x3efb183c, 0x3efd0fcd, 0x3eff06fa, 0x3f007ee2,
1618     0x3f017a16, 0x3f027519, 0x3f036fec, 0x3f046a8f, 0x3f056502, 0x3f065f47, 0x3f07595d, 0x3f085344,
1619     0x3f094cfe, 0x3f0a468b, 0x3f0b3feb, 0x3f0c391e, 0x3f0d3224, 0x3f0e2aff, 0x3f0f23af, 0x3f101c32,
1620     0x3f11148c, 0x3f120cba, 0x3f1304bf, 0x3f13fc9a, 0x3f14f44b, 0x3f15ebd3, 0x3f16e333, 0x3f17da6b,
1621     0x3f18d17a, 0x3f19c860, 0x3f1abf1f, 0x3f1bb5b7, 0x3f1cac28, 0x3f1da272, 0x3f1e9895, 0x3f1f8e92,
1622     0x3f20846a, 0x3f217a1c, 0x3f226fa8, 0x3f23650f, 0x3f245a52, 0x3f254f70, 0x3f264469, 0x3f27393f,
1623     0x3f282df1, 0x3f29227f, 0x3f2a16ea, 0x3f2b0b31, 0x3f2bff56, 0x3f2cf358, 0x3f2de738, 0x3f2edaf6,
1624     0x3f2fce91, 0x3f30c20b, 0x3f31b564, 0x3f32a89b, 0x3f339bb1, 0x3f348ea6, 0x3f35817a, 0x3f36742f,
1625     0x3f3766c3, 0x3f385936, 0x3f394b8a, 0x3f3a3dbe, 0x3f3b2fd3, 0x3f3c21c8, 0x3f3d139e, 0x3f3e0556,
1626     0x3f3ef6ee, 0x3f3fe868, 0x3f40d9c4, 0x3f41cb01, 0x3f42bc20, 0x3f43ad22, 0x3f449e06, 0x3f458ecc,
1627     0x3f467f75, 0x3f477001, 0x3f486071, 0x3f4950c2, 0x3f4a40f8, 0x3f4b3111, 0x3f4c210d, 0x3f4d10ed,
1628     0x3f4e00b2, 0x3f4ef05a, 0x3f4fdfe7, 0x3f50cf58, 0x3f51beae, 0x3f52ade8, 0x3f539d07, 0x3f548c0c,
1629     0x3f557af5, 0x3f5669c4, 0x3f575878, 0x3f584711, 0x3f593590, 0x3f5a23f6, 0x3f5b1241, 0x3f5c0072,
1630     0x3f5cee89, 0x3f5ddc87, 0x3f5eca6b, 0x3f5fb835, 0x3f60a5e7, 0x3f619380, 0x3f6280ff, 0x3f636e65,
1631     0x3f645bb3, 0x3f6548e8, 0x3f663604, 0x3f672309, 0x3f680ff4, 0x3f68fcc8, 0x3f69e983, 0x3f6ad627,
1632     0x3f6bc2b3, 0x3f6caf27, 0x3f6d9b83, 0x3f6e87c8, 0x3f6f73f5, 0x3f70600c, 0x3f714c0b, 0x3f7237f4,
1633     0x3f7323c4, 0x3f740f7f, 0x3f74fb22, 0x3f75e6af, 0x3f76d225, 0x3f77bd85, 0x3f78a8ce, 0x3f799401,
1634     0x3f7a7f1e, 0x3f7b6a25, 0x3f7c5516, 0x3f7d3ff1, 0x3f7e2ab6, 0x3f7f1566, 0x3f800000, 0x3f800000
1635 };
1636
1637 #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
1638 static inline XMVECTOR _TableEncodeGamma22( FXMVECTOR v )
1639 {
1640     float f[4];
1641     XMStoreFloat4( (XMFLOAT4*)f, v );
1642
1643     for( size_t i=0; i < 4; ++i )
1644     {
1645         float f2 = sqrtf(f[i]) * 254.0f;
1646
1647         uint32_t  i2 = static_cast<uint32_t>(f2);
1648         i2 = std::min<uint32_t>( i2, _countof( g_fEncodeGamma22 )-2 );
1649
1650         float fS = f2 - (float) i2;
1651         float fA = ((float *) g_fEncodeGamma22)[i2];
1652         float fB = ((float *) g_fEncodeGamma22)[i2 + 1];
1653
1654         f[i] = fA + fS * (fB - fA);
1655     }
1656
1657     return XMLoadFloat4( (XMFLOAT4*)f );
1658 }
1659
1660
1661 //-------------------------------------------------------------------------------------
1662 // sRGB -> RGB
1663 //-------------------------------------------------------------------------------------
1664 static const uint32_t g_fDecodeGamma22[] =
1665 {
1666     0x00000000, 0x3b144eb0, 0x3b9ef3b0, 0x3bf84b42, 0x3c2a5c46, 0x3c59c180, 0x3c850eb5, 0x3c9da52a,
1667     0x3cb6967a, 0x3ccfd852, 0x3ce9628b, 0x3d01974b, 0x3d0e9b82, 0x3d1bbba3, 0x3d28f5bc, 0x3d364822,
1668     0x3d43b159, 0x3d51301d, 0x3d5ec344, 0x3d6c69c9, 0x3d7a22c4, 0x3d83f6ad, 0x3d8ae465, 0x3d91da35,
1669     0x3d98d7c7, 0x3d9fdcd2, 0x3da6e914, 0x3dadfc47, 0x3db51635, 0x3dbc36a3, 0x3dc35d62, 0x3dca8a3a,
1670     0x3dd1bd02, 0x3dd8f591, 0x3de033bb, 0x3de7775d, 0x3deec050, 0x3df60e74, 0x3dfd61a6, 0x3e025ce5,
1671     0x3e060b61, 0x3e09bc38, 0x3e0d6f5f, 0x3e1124c8, 0x3e14dc68, 0x3e189630, 0x3e1c521a, 0x3e201016,
1672     0x3e23d01d, 0x3e279225, 0x3e2b5624, 0x3e2f1c10, 0x3e32e3e4, 0x3e36ad94, 0x3e3a7918, 0x3e3e4668,
1673     0x3e42157f, 0x3e45e654, 0x3e49b8e0, 0x3e4d8d1d, 0x3e516304, 0x3e553a8d, 0x3e5913b4, 0x3e5cee70,
1674     0x3e60cabf, 0x3e64a89b, 0x3e6887fb, 0x3e6c68db, 0x3e704b3a, 0x3e742f0e, 0x3e781454, 0x3e7bfb04,
1675     0x3e7fe321, 0x3e81e650, 0x3e83dbc0, 0x3e85d1dc, 0x3e87c8a3, 0x3e89c015, 0x3e8bb830, 0x3e8db0ee,
1676     0x3e8faa51, 0x3e91a454, 0x3e939ef9, 0x3e959a3b, 0x3e97961b, 0x3e999295, 0x3e9b8fa7, 0x3e9d8d52,
1677     0x3e9f8b93, 0x3ea18a6a, 0x3ea389d2, 0x3ea589cb, 0x3ea78a56, 0x3ea98b6e, 0x3eab8d15, 0x3ead8f47,
1678     0x3eaf9204, 0x3eb1954a, 0x3eb39917, 0x3eb59d6c, 0x3eb7a246, 0x3eb9a7a5, 0x3ebbad88, 0x3ebdb3ec,
1679     0x3ebfbad3, 0x3ec1c237, 0x3ec3ca1a, 0x3ec5d27c, 0x3ec7db58, 0x3ec9e4b4, 0x3ecbee85, 0x3ecdf8d3,
1680     0x3ed0039a, 0x3ed20ed8, 0x3ed41a8a, 0x3ed626b5, 0x3ed83351, 0x3eda4065, 0x3edc4de9, 0x3ede5be0,
1681     0x3ee06a4a, 0x3ee27923, 0x3ee4886a, 0x3ee69821, 0x3ee8a845, 0x3eeab8d8, 0x3eecc9d6, 0x3eeedb3f,
1682     0x3ef0ed13, 0x3ef2ff53, 0x3ef511fb, 0x3ef7250a, 0x3ef93883, 0x3efb4c61, 0x3efd60a7, 0x3eff7553,
1683     0x3f00c531, 0x3f01cfeb, 0x3f02dad9, 0x3f03e5f5, 0x3f04f145, 0x3f05fcc4, 0x3f070875, 0x3f081456,
1684     0x3f092067, 0x3f0a2ca8, 0x3f0b3917, 0x3f0c45b7, 0x3f0d5284, 0x3f0e5f7f, 0x3f0f6caa, 0x3f107a03,
1685     0x3f118789, 0x3f12953b, 0x3f13a31d, 0x3f14b12b, 0x3f15bf64, 0x3f16cdca, 0x3f17dc5e, 0x3f18eb1b,
1686     0x3f19fa05, 0x3f1b091b, 0x3f1c185c, 0x3f1d27c7, 0x3f1e375c, 0x3f1f471d, 0x3f205707, 0x3f21671b,
1687     0x3f227759, 0x3f2387c2, 0x3f249852, 0x3f25a90c, 0x3f26b9ef, 0x3f27cafb, 0x3f28dc30, 0x3f29ed8b,
1688     0x3f2aff11, 0x3f2c10bd, 0x3f2d2290, 0x3f2e348b, 0x3f2f46ad, 0x3f3058f7, 0x3f316b66, 0x3f327dfd,
1689     0x3f3390ba, 0x3f34a39d, 0x3f35b6a7, 0x3f36c9d6, 0x3f37dd2b, 0x3f38f0a5, 0x3f3a0443, 0x3f3b1808,
1690     0x3f3c2bf2, 0x3f3d4000, 0x3f3e5434, 0x3f3f688c, 0x3f407d07, 0x3f4191a8, 0x3f42a66c, 0x3f43bb54,
1691     0x3f44d05f, 0x3f45e58e, 0x3f46fadf, 0x3f481054, 0x3f4925ed, 0x3f4a3ba8, 0x3f4b5186, 0x3f4c6789,
1692     0x3f4d7daa, 0x3f4e93f0, 0x3f4faa57, 0x3f50c0e0, 0x3f51d78b, 0x3f52ee58, 0x3f540545, 0x3f551c55,
1693     0x3f563386, 0x3f574ad7, 0x3f58624b, 0x3f5979de, 0x3f5a9191, 0x3f5ba965, 0x3f5cc15b, 0x3f5dd971,
1694     0x3f5ef1a6, 0x3f6009fc, 0x3f612272, 0x3f623b08, 0x3f6353bc, 0x3f646c90, 0x3f658586, 0x3f669e98,
1695     0x3f67b7cb, 0x3f68d11b, 0x3f69ea8d, 0x3f6b041b, 0x3f6c1dc9, 0x3f6d3795, 0x3f6e5180, 0x3f6f6b8b,
1696     0x3f7085b2, 0x3f719ff7, 0x3f72ba5b, 0x3f73d4dc, 0x3f74ef7c, 0x3f760a38, 0x3f772512, 0x3f78400b,
1697     0x3f795b20, 0x3f7a7651, 0x3f7b91a2, 0x3f7cad0e, 0x3f7dc896, 0x3f7ee43c, 0x3f800000, 0x3f800000
1698 };
1699
1700
1701 #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
1702 static inline XMVECTOR _TableDecodeGamma22( FXMVECTOR v )
1703 {
1704     float f[4];
1705     XMStoreFloat4( (XMFLOAT4*)f, v );
1706
1707     for( size_t i=0; i < 4; ++i )
1708     {
1709         float f2 = f[i] * f[i] * 254.0f;
1710         uint32_t  i2 = static_cast<uint32_t>(f2);
1711         i2 = std::min<uint32_t>( i2, _countof(g_fDecodeGamma22)-2 );
1712
1713         float fS = f2 - (float) i2;
1714         float fA = ((float *) g_fDecodeGamma22)[i2];
1715         float fB = ((float *) g_fDecodeGamma22)[i2 + 1];
1716
1717         f[i] = fA + fS * (fB - fA);
1718     }
1719
1720     return XMLoadFloat4( (XMFLOAT4*)f );
1721 }
1722
1723
1724 //-------------------------------------------------------------------------------------
1725 // Convert scanline based on source/target formats
1726 //-------------------------------------------------------------------------------------
1727 struct ConvertData
1728 {
1729     DXGI_FORMAT format;
1730     size_t datasize;
1731     DWORD flags;
1732 };
1733
1734 static const ConvertData g_ConvertTable[] = {
1735     { DXGI_FORMAT_R32G32B32A32_FLOAT,           32, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1736     { DXGI_FORMAT_R32G32B32A32_UINT,            32, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1737     { DXGI_FORMAT_R32G32B32A32_SINT,            32, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1738     { DXGI_FORMAT_R32G32B32_FLOAT,              32, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B },
1739     { DXGI_FORMAT_R32G32B32_UINT,               32, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B },
1740     { DXGI_FORMAT_R32G32B32_SINT,               32, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B },
1741     { DXGI_FORMAT_R16G16B16A16_FLOAT,           16, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1742     { DXGI_FORMAT_R16G16B16A16_UNORM,           16, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, 
1743     { DXGI_FORMAT_R16G16B16A16_UINT,            16, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, 
1744     { DXGI_FORMAT_R16G16B16A16_SNORM,           16, CONVF_SNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, 
1745     { DXGI_FORMAT_R16G16B16A16_SINT,            16, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A }, 
1746     { DXGI_FORMAT_R32G32_FLOAT,                 32, CONVF_FLOAT | CONVF_R | CONVF_G },
1747     { DXGI_FORMAT_R32G32_UINT,                  32, CONVF_UINT | CONVF_R | CONVF_G  },
1748     { DXGI_FORMAT_R32G32_SINT,                  32, CONVF_SINT | CONVF_R | CONVF_G  },
1749     { DXGI_FORMAT_D32_FLOAT_S8X24_UINT,         32, CONVF_FLOAT | CONVF_DEPTH | CONVF_STENCIL },
1750     { DXGI_FORMAT_R10G10B10A2_UNORM,            10, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1751     { DXGI_FORMAT_R10G10B10A2_UINT,             10, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1752     { DXGI_FORMAT_R11G11B10_FLOAT,              10, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B },
1753     { DXGI_FORMAT_R8G8B8A8_UNORM,               8, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1754     { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,          8, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1755     { DXGI_FORMAT_R8G8B8A8_UINT,                8, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1756     { DXGI_FORMAT_R8G8B8A8_SNORM,               8, CONVF_SNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1757     { DXGI_FORMAT_R8G8B8A8_SINT,                8, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1758     { DXGI_FORMAT_R16G16_FLOAT,                 16, CONVF_FLOAT | CONVF_R | CONVF_G },
1759     { DXGI_FORMAT_R16G16_UNORM,                 16, CONVF_UNORM | CONVF_R | CONVF_G },
1760     { DXGI_FORMAT_R16G16_UINT,                  16, CONVF_UINT | CONVF_R | CONVF_G },
1761     { DXGI_FORMAT_R16G16_SNORM,                 16, CONVF_SNORM | CONVF_R | CONVF_G },
1762     { DXGI_FORMAT_R16G16_SINT,                  16, CONVF_SINT | CONVF_R | CONVF_G },
1763     { DXGI_FORMAT_D32_FLOAT,                    32, CONVF_FLOAT | CONVF_DEPTH },
1764     { DXGI_FORMAT_R32_FLOAT,                    32, CONVF_FLOAT | CONVF_R },
1765     { DXGI_FORMAT_R32_UINT,                     32, CONVF_UINT | CONVF_R },
1766     { DXGI_FORMAT_R32_SINT,                     32, CONVF_SINT | CONVF_R },
1767     { DXGI_FORMAT_D24_UNORM_S8_UINT,            32, CONVF_UNORM | CONVF_DEPTH | CONVF_STENCIL },
1768     { DXGI_FORMAT_R8G8_UNORM,                   8, CONVF_UNORM | CONVF_R | CONVF_G },
1769     { DXGI_FORMAT_R8G8_UINT,                    8, CONVF_UINT | CONVF_R | CONVF_G },
1770     { DXGI_FORMAT_R8G8_SNORM,                   8, CONVF_SNORM | CONVF_R | CONVF_G },
1771     { DXGI_FORMAT_R8G8_SINT,                    8, CONVF_SINT | CONVF_R | CONVF_G },
1772     { DXGI_FORMAT_R16_FLOAT,                    16, CONVF_FLOAT | CONVF_R },
1773     { DXGI_FORMAT_D16_UNORM,                    16, CONVF_UNORM | CONVF_DEPTH },
1774     { DXGI_FORMAT_R16_UNORM,                    16, CONVF_UNORM | CONVF_R },
1775     { DXGI_FORMAT_R16_UINT,                     16, CONVF_UINT | CONVF_R },
1776     { DXGI_FORMAT_R16_SNORM,                    16, CONVF_SNORM | CONVF_R },
1777     { DXGI_FORMAT_R16_SINT,                     16, CONVF_SINT | CONVF_R },
1778     { DXGI_FORMAT_R8_UNORM,                     8, CONVF_UNORM | CONVF_R },
1779     { DXGI_FORMAT_R8_UINT,                      8, CONVF_UINT | CONVF_R },
1780     { DXGI_FORMAT_R8_SNORM,                     8, CONVF_SNORM | CONVF_R },
1781     { DXGI_FORMAT_R8_SINT,                      8, CONVF_SINT | CONVF_R },
1782     { DXGI_FORMAT_A8_UNORM,                     8, CONVF_UNORM | CONVF_A },
1783     { DXGI_FORMAT_R1_UNORM,                     1, CONVF_UNORM | CONVF_R },
1784     { DXGI_FORMAT_R9G9B9E5_SHAREDEXP,           9, CONVF_SHAREDEXP | CONVF_R | CONVF_G | CONVF_B },
1785     { DXGI_FORMAT_R8G8_B8G8_UNORM,              8, CONVF_UNORM | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B },
1786     { DXGI_FORMAT_G8R8_G8B8_UNORM,              8, CONVF_UNORM | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B },
1787     { DXGI_FORMAT_BC1_UNORM,                    8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1788     { DXGI_FORMAT_BC1_UNORM_SRGB,               8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1789     { DXGI_FORMAT_BC2_UNORM,                    8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1790     { DXGI_FORMAT_BC2_UNORM_SRGB,               8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1791     { DXGI_FORMAT_BC3_UNORM,                    8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1792     { DXGI_FORMAT_BC3_UNORM_SRGB,               8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1793     { DXGI_FORMAT_BC4_UNORM,                    8, CONVF_UNORM | CONVF_BC | CONVF_R },
1794     { DXGI_FORMAT_BC4_SNORM,                    8, CONVF_SNORM | CONVF_BC | CONVF_R },
1795     { DXGI_FORMAT_BC5_UNORM,                    8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G },
1796     { DXGI_FORMAT_BC5_SNORM,                    8, CONVF_SNORM | CONVF_BC | CONVF_R | CONVF_G },
1797     { DXGI_FORMAT_B5G6R5_UNORM,                 5, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B },
1798     { DXGI_FORMAT_B5G5R5A1_UNORM,               5, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1799     { DXGI_FORMAT_B8G8R8A8_UNORM,               8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1800     { DXGI_FORMAT_B8G8R8X8_UNORM,               8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B },
1801     { DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM,   10, CONVF_UNORM | CONVF_X2 | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1802     { DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,          8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1803     { DXGI_FORMAT_B8G8R8X8_UNORM_SRGB,          8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B },
1804     { DXGI_FORMAT_BC6H_UF16,                    16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1805     { DXGI_FORMAT_BC6H_SF16,                    16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1806     { DXGI_FORMAT_BC7_UNORM,                    8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1807     { DXGI_FORMAT_BC7_UNORM_SRGB,               8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1808 #ifdef DXGI_1_2_FORMATS
1809     { DXGI_FORMAT_B4G4R4A4_UNORM,               4, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1810 #endif
1811 };
1812
1813 #pragma prefast( suppress : 25004, "Signature must match bsearch" );
1814 static int __cdecl _ConvertCompare( const void* ptr1, const void *ptr2 )
1815 {
1816     const ConvertData *p1 = reinterpret_cast<const ConvertData*>(ptr1);
1817     const ConvertData *p2 = reinterpret_cast<const ConvertData*>(ptr2);
1818     if ( p1->format == p2->format ) return 0;
1819     else return (p1->format < p2->format ) ? -1 : 1;
1820 }
1821
1822 DWORD _GetConvertFlags( DXGI_FORMAT format )
1823 {
1824 #ifdef _DEBUG
1825     // Ensure conversion table is in ascending order
1826     assert( _countof(g_ConvertTable) > 0 );
1827     DXGI_FORMAT lastvalue = g_ConvertTable[0].format;
1828     for( size_t index=1; index < _countof(g_ConvertTable); ++index )
1829     {
1830         assert( g_ConvertTable[index].format > lastvalue );
1831         lastvalue = g_ConvertTable[index].format;
1832     }
1833 #endif
1834
1835     ConvertData key = { format, 0 };
1836     const ConvertData* in = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1837                                                           _ConvertCompare );
1838     return (in) ? in->flags : 0;
1839 }
1840
1841 void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, DXGI_FORMAT inFormat, DWORD flags )
1842 {
1843 #if !defined(_XM_NO_INTRINSICS_)
1844     assert( pBuffer && count > 0 && (((uintptr_t)pBuffer & 0xF) == 0) );
1845 #endif
1846     assert( IsValid(outFormat) && !IsVideo(outFormat) && !IsTypeless(outFormat) );
1847     assert( IsValid(inFormat) && !IsVideo(inFormat) && !IsTypeless(inFormat) );
1848
1849     if ( !pBuffer )
1850         return;
1851
1852 #ifdef _DEBUG
1853     // Ensure conversion table is in ascending order
1854     assert( _countof(g_ConvertTable) > 0 );
1855     DXGI_FORMAT lastvalue = g_ConvertTable[0].format;
1856     for( size_t index=1; index < _countof(g_ConvertTable); ++index )
1857     {
1858         assert( g_ConvertTable[index].format > lastvalue );
1859         lastvalue = g_ConvertTable[index].format;
1860     }
1861 #endif
1862
1863     // Determine conversion details about source and dest formats
1864     ConvertData key = { inFormat, 0 };
1865     const ConvertData* in = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1866                                                           _ConvertCompare );
1867     key.format = outFormat;
1868     const ConvertData* out = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1869                                                            _ConvertCompare );
1870     if ( !in || !out )
1871     {
1872         assert(false);
1873         return;
1874     }
1875
1876     assert( _GetConvertFlags( inFormat ) == in->flags );
1877     assert( _GetConvertFlags( outFormat ) == out->flags );
1878
1879     // Handle SRGB filtering modes
1880     if ( IsSRGB( inFormat ) )
1881         flags |= TEX_FILTER_SRGB_IN;
1882
1883     if ( IsSRGB( outFormat ) )
1884         flags |= TEX_FILTER_SRGB_OUT;
1885
1886     if ( in->flags & CONVF_SNORM )
1887         flags &= ~TEX_FILTER_SRGB_IN;
1888
1889     if ( out->flags & CONVF_SNORM )
1890         flags &= ~TEX_FILTER_SRGB_OUT;
1891
1892     if ( (flags & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
1893     {
1894         flags &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
1895     }
1896
1897     // sRGB input processing (sRGB -> RGB)
1898     if ( flags & TEX_FILTER_SRGB_IN )
1899     {
1900         if ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) )
1901         {
1902             XMVECTOR* ptr = pBuffer;
1903             for( size_t i=0; i < count; ++i )
1904             {
1905                 // rgb = rgb^(2.2); a=a
1906                 XMVECTOR v = *ptr;
1907                 XMVECTOR v1 = _TableDecodeGamma22( v );
1908                 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
1909             }
1910         }
1911     }
1912
1913     // Handle conversion special cases
1914     DWORD diffFlags = in->flags ^ out->flags;
1915     if ( diffFlags != 0)
1916     {
1917         if ( out->flags & CONVF_UNORM )
1918         {
1919             if ( in->flags & CONVF_SNORM )
1920             {
1921                 // SNORM -> UNORM
1922                 XMVECTOR* ptr = pBuffer;
1923                 for( size_t i=0; i < count; ++i )
1924                 {
1925                     XMVECTOR v = *ptr;
1926                     *ptr++ = XMVectorMultiplyAdd( v, g_XMOneHalf, g_XMOneHalf );
1927                 }
1928             }
1929             else if ( in->flags & CONVF_FLOAT )
1930             {
1931                 // FLOAT -> UNORM
1932                 XMVECTOR* ptr = pBuffer;
1933                 for( size_t i=0; i < count; ++i )
1934                 {
1935                     XMVECTOR v = *ptr;
1936                     *ptr++ = XMVectorSaturate( v );
1937                 }
1938             }
1939         }
1940         else if ( out->flags & CONVF_SNORM )
1941         {
1942             if ( in->flags & CONVF_UNORM )
1943             {
1944                 // UNORM -> SNORM
1945                 static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
1946                 XMVECTOR* ptr = pBuffer;
1947                 for( size_t i=0; i < count; ++i )
1948                 {
1949                     XMVECTOR v = *ptr;
1950                     *ptr++ = XMVectorMultiplyAdd( v, two, g_XMNegativeOne );
1951                 }
1952             }
1953             else if ( in->flags & CONVF_FLOAT )
1954             {
1955                 // FLOAT -> SNORM
1956                 XMVECTOR* ptr = pBuffer;
1957                 for( size_t i=0; i < count; ++i )
1958                 {
1959                     XMVECTOR v = *ptr;
1960                     *ptr++ = XMVectorClamp( v, g_XMNegativeOne, g_XMOne );
1961                 }
1962             }
1963         }
1964
1965         // !CONVF_A -> CONVF_A is handled because LoadScanline ensures alpha defaults to 1.0 for no-alpha formats
1966
1967         // CONVF_PACKED cases are handled because LoadScanline/StoreScanline handles packing/unpacking
1968
1969         if ( ((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A) )
1970         {
1971             // !CONVF_A -> A format
1972             XMVECTOR* ptr = pBuffer;
1973             for( size_t i=0; i < count; ++i )
1974             {
1975                 XMVECTOR v = *ptr;
1976                 *ptr++ = XMVectorSplatX( v );
1977             }
1978         }
1979         else if ( ((in->flags & CONVF_RGBA_MASK) == CONVF_A) && !(out->flags & CONVF_A) )
1980         {
1981             // A format -> !CONVF_A
1982             XMVECTOR* ptr = pBuffer;
1983             for( size_t i=0; i < count; ++i )
1984             {
1985                 XMVECTOR v = *ptr;
1986                 *ptr++ = XMVectorSplatW( v );
1987             }
1988         }
1989         else if ( ((in->flags & CONVF_RGB_MASK) == CONVF_R) && ((out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B)) )
1990         {
1991             // R format -> RGB format
1992             XMVECTOR* ptr = pBuffer;
1993             for( size_t i=0; i < count; ++i )
1994             {
1995                 XMVECTOR v = *ptr;
1996                 XMVECTOR v1 = XMVectorSplatX( v );
1997                 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
1998             }
1999         }
2000     }
2001
2002     // sRGB output processing (RGB -> sRGB)
2003     if ( flags & TEX_FILTER_SRGB_OUT )
2004     {
2005         if ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) )
2006         {
2007             XMVECTOR* ptr = pBuffer;
2008             for( size_t i=0; i < count; ++i )
2009             {
2010                 // rgb = rgb^(1/2.2); a=a
2011                 XMVECTOR v = *ptr;
2012                 XMVECTOR v1 = _TableEncodeGamma22( v );
2013                 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
2014             }
2015         }
2016     }
2017 }
2018
2019
2020 //-------------------------------------------------------------------------------------
2021 // Convert the source image using WIC
2022 //-------------------------------------------------------------------------------------
2023 static HRESULT _ConvertUsingWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
2024                                  _In_ const WICPixelFormatGUID& targetGUID,
2025                                  _In_ DWORD filter, _In_ float threshold,  _In_ const Image& destImage )
2026 {
2027     assert( srcImage.width == destImage.width );
2028     assert( srcImage.height == destImage.height );
2029
2030     IWICImagingFactory* pWIC = _GetWIC();
2031     if ( !pWIC )
2032         return E_NOINTERFACE;
2033
2034     ScopedObject<IWICFormatConverter> FC;
2035     HRESULT hr = pWIC->CreateFormatConverter( &FC );
2036     if ( FAILED(hr) )
2037         return hr;
2038
2039     // Need to implement usage of TEX_FILTER_SRGB_IN/TEX_FILTER_SRGB_OUT
2040
2041     BOOL canConvert = FALSE;
2042     hr = FC->CanConvert( pfGUID, targetGUID, &canConvert );
2043     if ( FAILED(hr) || !canConvert )
2044     {
2045         // This case is not an issue for the subset of WIC formats that map directly to DXGI
2046         return E_UNEXPECTED;
2047     }
2048
2049     ScopedObject<IWICBitmap> source;
2050     hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
2051                                        static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
2052                                        srcImage.pixels, &source );
2053     if ( FAILED(hr) )
2054         return hr;
2055
2056     hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2057     if ( FAILED(hr) )
2058         return hr;
2059
2060     hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );  
2061     if ( FAILED(hr) )
2062         return hr;
2063
2064     return S_OK;
2065 }
2066
2067
2068 //-------------------------------------------------------------------------------------
2069 // Convert the source using WIC and then convert to DXGI format from there
2070 //-------------------------------------------------------------------------------------
2071 static HRESULT _ConvertFromWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
2072                                 _In_ DWORD filter, _In_ float threshold,  _In_ const Image& destImage )
2073 {
2074     assert( srcImage.width == destImage.width );
2075     assert( srcImage.height == destImage.height );
2076
2077     IWICImagingFactory* pWIC = _GetWIC();
2078     if ( !pWIC )
2079         return E_NOINTERFACE;
2080
2081     ScopedObject<IWICFormatConverter> FC;
2082     HRESULT hr = pWIC->CreateFormatConverter( &FC );
2083     if ( FAILED(hr) )
2084         return hr;
2085
2086     BOOL canConvert = FALSE;
2087     hr = FC->CanConvert( pfGUID, GUID_WICPixelFormat128bppRGBAFloat, &canConvert );
2088     if ( FAILED(hr) || !canConvert )
2089     {
2090         // This case is not an issue for the subset of WIC formats that map directly to DXGI
2091         return E_UNEXPECTED;
2092     }
2093
2094     ScratchImage temp;
2095     hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2096     if ( FAILED(hr) )
2097         return hr;
2098
2099     const Image *timg = temp.GetImage( 0, 0, 0 );
2100     if ( !timg )
2101         return E_POINTER;
2102
2103     ScopedObject<IWICBitmap> source;
2104     hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
2105                                        static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
2106                                        srcImage.pixels, &source );
2107     if ( FAILED(hr) )
2108         return hr;
2109
2110     hr = FC->Initialize( source.Get(), GUID_WICPixelFormat128bppRGBAFloat, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2111     if ( FAILED(hr) )
2112         return hr;
2113
2114     hr = FC->CopyPixels( 0, static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ), timg->pixels );  
2115     if ( FAILED(hr) )
2116         return hr;
2117
2118     // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format to final image
2119     uint8_t *pSrc = timg->pixels;
2120     uint8_t *pDest = destImage.pixels;
2121     if ( !pSrc || !pDest )
2122         return E_POINTER;
2123
2124     for( size_t h = 0; h < srcImage.height; ++h )
2125     {
2126         _ConvertScanline( reinterpret_cast<XMVECTOR*>(pSrc), srcImage.width, destImage.format, DXGI_FORMAT_R32G32B32A32_FLOAT, filter );
2127
2128         if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
2129             return E_FAIL;
2130
2131         pSrc += timg->rowPitch;
2132         pDest += destImage.rowPitch;
2133     }
2134
2135     return S_OK;
2136 }
2137
2138
2139 //-------------------------------------------------------------------------------------
2140 // Convert the source from DXGI format then use WIC to convert to final format
2141 //-------------------------------------------------------------------------------------
2142 static HRESULT _ConvertToWIC( _In_ const Image& srcImage, 
2143                               _In_ const WICPixelFormatGUID& targetGUID, _In_ DWORD filter, _In_ float threshold,  _In_ const Image& destImage )
2144 {
2145     assert( srcImage.width == destImage.width );
2146     assert( srcImage.height == destImage.height );
2147
2148     IWICImagingFactory* pWIC = _GetWIC();
2149     if ( !pWIC )
2150         return E_NOINTERFACE;
2151
2152     ScopedObject<IWICFormatConverter> FC;
2153     HRESULT hr = pWIC->CreateFormatConverter( &FC );
2154     if ( FAILED(hr) )
2155         return hr;
2156
2157     BOOL canConvert = FALSE;
2158     hr = FC->CanConvert( GUID_WICPixelFormat128bppRGBAFloat, targetGUID, &canConvert );
2159     if ( FAILED(hr) || !canConvert )
2160     {
2161         // This case is not an issue for the subset of WIC formats that map directly to DXGI
2162         return E_UNEXPECTED;
2163     }
2164
2165     ScratchImage temp;
2166     hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2167     if ( FAILED(hr) )
2168         return hr;
2169
2170     const Image *timg = temp.GetImage( 0, 0, 0 );
2171     if ( !timg )
2172         return E_POINTER;
2173
2174     const uint8_t *pSrc = srcImage.pixels;
2175     if ( !pSrc )
2176         return E_POINTER;
2177
2178     uint8_t *pDest = timg->pixels;
2179     if ( !pDest )
2180         return E_POINTER;
2181
2182     for( size_t h = 0; h < srcImage.height; ++h )
2183     {
2184         if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2185             return E_FAIL;
2186
2187         _ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
2188
2189         pSrc += srcImage.rowPitch;
2190         pDest += timg->rowPitch;
2191     }
2192
2193     // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format
2194     ScopedObject<IWICBitmap> source;
2195     hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( timg->width ), static_cast<UINT>( timg->height ), GUID_WICPixelFormat128bppRGBAFloat,
2196                                        static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ),
2197                                        timg->pixels, &source );
2198     if ( FAILED(hr) )
2199         return hr;
2200
2201     hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2202     if ( FAILED(hr) )
2203         return hr;
2204
2205     hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );  
2206     if ( FAILED(hr) )
2207         return hr;
2208
2209     return S_OK;
2210 }
2211
2212
2213 //-------------------------------------------------------------------------------------
2214 // Convert the source image (not using WIC)
2215 //-------------------------------------------------------------------------------------
2216 static HRESULT _Convert( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
2217 {
2218     assert( srcImage.width == destImage.width );
2219     assert( srcImage.height == destImage.height );
2220
2221     ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
2222     if ( !scanline )
2223         return E_OUTOFMEMORY;
2224
2225     const uint8_t *pSrc = srcImage.pixels;
2226     uint8_t *pDest = destImage.pixels;
2227     if ( !pSrc || !pDest )
2228         return E_POINTER;
2229
2230     for( size_t h = 0; h < srcImage.height; ++h )
2231     {
2232         if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2233             return E_FAIL;
2234
2235         _ConvertScanline( scanline.get(), srcImage.width, destImage.format, srcImage.format, filter );
2236
2237         if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
2238             return E_FAIL;
2239
2240         pSrc += srcImage.rowPitch;
2241         pDest += destImage.rowPitch;
2242     }
2243
2244     return S_OK;
2245 }
2246
2247
2248 //=====================================================================================
2249 // Entry-points
2250 //=====================================================================================
2251
2252 //-------------------------------------------------------------------------------------
2253 // Convert image
2254 //-------------------------------------------------------------------------------------
2255 HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& image )
2256 {
2257     if ( (srcImage.format == format) || !IsValid( format ) )
2258         return E_INVALIDARG;
2259
2260     if ( !srcImage.pixels )
2261         return E_POINTER;
2262
2263     if ( IsCompressed(srcImage.format) || IsCompressed(format)
2264          || IsVideo(srcImage.format) || IsVideo(format) 
2265          || IsTypeless(srcImage.format) || IsTypeless(format) )
2266         return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
2267
2268 #ifdef _AMD64_
2269     if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
2270         return E_INVALIDARG;
2271 #endif
2272
2273     HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
2274     if ( FAILED(hr) )
2275         return hr;
2276    
2277     const Image *rimage = image.GetImage( 0, 0, 0 );
2278     if ( !rimage )
2279     {
2280         image.Release();
2281         return E_POINTER;
2282     }
2283
2284     WICPixelFormatGUID pfGUID;
2285     if ( _DXGIToWIC( srcImage.format, pfGUID ) )
2286     {
2287         WICPixelFormatGUID targetGUID;
2288         if ( _DXGIToWIC( format, targetGUID ) )
2289         {
2290             // Case 1: Both source and target formats are WIC supported
2291             hr = _ConvertUsingWIC( srcImage, pfGUID, targetGUID, filter, threshold, *rimage );
2292         }
2293         else
2294         {
2295             // Case 2: Source format is supported by WIC, but not the target format
2296             hr = _ConvertFromWIC( srcImage, pfGUID, filter, threshold, *rimage );
2297         }
2298     }
2299     else
2300     {
2301         WICPixelFormatGUID targetGUID;
2302         if ( _DXGIToWIC( format, targetGUID ) )
2303         {
2304             // Case 3: Source format is not supported by WIC, but does support the target format
2305             hr = _ConvertToWIC( srcImage, targetGUID, filter, threshold, *rimage );
2306         }
2307         else
2308         {
2309             // Case 4: Both source and target format are not supported by WIC
2310             hr = _Convert( srcImage, filter, *rimage );
2311         }
2312     }
2313
2314     if ( FAILED(hr) )
2315     {
2316         image.Release();
2317         return hr;
2318     }
2319
2320     return S_OK;
2321 }
2322
2323
2324 //-------------------------------------------------------------------------------------
2325 // Convert image (complex)
2326 //-------------------------------------------------------------------------------------
2327 HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
2328                  DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& result )
2329 {
2330     if ( !srcImages || !nimages || (metadata.format == format) || !IsValid(format) )
2331         return E_INVALIDARG;
2332
2333     if ( IsCompressed(metadata.format) || IsCompressed(format)
2334          || IsVideo(metadata.format) || IsVideo(format) 
2335          || IsTypeless(metadata.format) || IsTypeless(format) )
2336         return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
2337
2338 #ifdef _AMD64_
2339     if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
2340         return E_INVALIDARG;
2341 #endif
2342
2343     TexMetadata mdata2 = metadata;
2344     mdata2.format = format;
2345     HRESULT hr = result.Initialize( mdata2 );
2346     if ( FAILED(hr) )
2347         return hr;
2348
2349     if ( nimages != result.GetImageCount() )
2350     {
2351         result.Release();
2352         return E_FAIL;
2353     }
2354
2355     const Image* dest = result.GetImages();
2356     if ( !dest )
2357     {
2358         result.Release();
2359         return E_POINTER;
2360     }
2361
2362     WICPixelFormatGUID pfGUID, targetGUID;
2363     bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
2364     bool wictargetpf = _DXGIToWIC( format, targetGUID );
2365
2366     for( size_t index=0; index < nimages; ++index )
2367     {
2368         const Image& src = srcImages[ index ];
2369         if ( src.format != metadata.format )
2370         {
2371             result.Release();
2372             return E_FAIL;
2373         }
2374
2375 #ifdef _AMD64_
2376         if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
2377             return E_FAIL;
2378 #endif
2379
2380         const Image& dst = dest[ index ];
2381         assert( dst.format == format );
2382
2383         if ( src.width != dst.width || src.height != dst.height )
2384         {
2385             result.Release();
2386             return E_FAIL;
2387         }
2388
2389         if ( wicpf )
2390         {
2391             if ( wictargetpf )
2392             {
2393                 // Case 1: Both source and target formats are WIC supported
2394                 hr = _ConvertUsingWIC( src, pfGUID, targetGUID, filter, threshold, dst );
2395             }
2396             else
2397             {
2398                 // Case 2: Source format is supported by WIC, but not the target format
2399                 hr = _ConvertFromWIC( src, pfGUID, filter, threshold, dst );
2400             }
2401         }
2402         else
2403         {
2404             if ( wictargetpf )
2405             {
2406                 // Case 3: Source format is not supported by WIC, but does support the target format
2407                 hr = _ConvertToWIC( src, targetGUID, filter, threshold, dst );
2408             }
2409             else
2410             {
2411                 // Case 4: Both source and target format are not supported by WIC
2412                 hr = _Convert( src, filter, dst );
2413             }
2414         }
2415
2416         if ( FAILED(hr) )
2417         {
2418             result.Release();
2419             return hr;
2420         }
2421     }
2422
2423     return S_OK;
2424 }
2425
2426 }; // namespace