1 //-------------------------------------------------------------------------------------
2 // DirectXTexConvert.cpp
4 // DirectX Texture Library - Image conversion
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
11 // Copyright (c) Microsoft Corporation. All rights reserved.
13 // http://go.microsoft.com/fwlink/?LinkId=248926
14 //-------------------------------------------------------------------------------------
16 #include "DirectXTexP.h"
19 #if XNAMATH_VERSION < 205
20 #error This file requires XNAMATH v2.05 or later
23 using namespace DirectX::PackedVector;
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 )
35 assert( pDestination && outSize > 0 );
36 assert( pSource && inSize > 0 );
37 assert( IsValid(format) && !IsVideo(format) );
39 if ( flags & TEXP_SCANLINE_SETALPHA )
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:
50 if ( format == DXGI_FORMAT_R32G32B32A32_FLOAT )
52 else if ( format == DXGI_FORMAT_R32G32B32A32_SINT )
57 if ( pDestination == pSource )
59 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
60 for( size_t count = 0; count < outSize; count += 16 )
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 )
73 *(dPtr++) = *(sPtr++);
74 *(dPtr++) = *(sPtr++);
75 *(dPtr++) = *(sPtr++);
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:
92 if ( format == DXGI_FORMAT_R16G16B16A16_FLOAT )
94 else if ( format == DXGI_FORMAT_R16G16B16A16_SNORM || format == DXGI_FORMAT_R16G16B16A16_SINT )
99 if ( pDestination == pSource )
101 uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
102 for( size_t count = 0; count < outSize; count += 8 )
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 )
115 *(dPtr++) = *(sPtr++);
116 *(dPtr++) = *(sPtr++);
117 *(dPtr++) = *(sPtr++);
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 )
132 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
133 for( size_t count = 0; count < outSize; count += 4 )
135 #pragma warning(suppress: 6001 6101) // PREFast doesn't properly understand the aliasing here.
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 )
147 *(dPtr++) = *(sPtr++) | 0xC0000000;
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:
163 const uint32_t alpha = ( format == DXGI_FORMAT_R8G8B8A8_SNORM || format == DXGI_FORMAT_R8G8B8A8_SINT ) ? 0x7f000000 : 0xff000000;
165 if ( pDestination == pSource )
167 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
168 for( size_t count = 0; count < outSize; count += 4 )
170 uint32_t t = *dPtr & 0xFFFFFF;
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 )
182 uint32_t t = *(sPtr++) & 0xFFFFFF;
190 //-----------------------------------------------------------------------------
191 case DXGI_FORMAT_B5G5R5A1_UNORM:
192 if ( pDestination == pSource )
194 uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
195 for( size_t count = 0; count < outSize; count += 2 )
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 )
207 *(dPtr++) = *(sPtr++) | 0x8000;
212 //-----------------------------------------------------------------------------
213 case DXGI_FORMAT_A8_UNORM:
214 memset( pDestination, 0xff, outSize );
217 #ifdef DXGI_1_2_FORMATS
218 //-----------------------------------------------------------------------------
219 case DXGI_FORMAT_B4G4R4A4_UNORM:
220 if ( pDestination == pSource )
222 uint16_t *dPtr = reinterpret_cast<uint16_t*>(pDestination);
223 for( size_t count = 0; count < outSize; count += 2 )
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 )
235 *(dPtr++) = *(sPtr++) | 0xF000;
239 #endif // DXGI_1_2_FORMATS
243 // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
244 if ( pDestination == pSource )
247 size_t size = std::min<size_t>( outSize, inSize );
248 memcpy_s( pDestination, outSize, pSource, size );
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 )
258 assert( pDestination && outSize > 0 );
259 assert( pSource && inSize > 0 );
260 assert( IsValid(format) && !IsVideo(format) );
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 )
271 // Swap Red (R) and Blue (B) channel (used for D3DFMT_A2R10G10B10 legacy sources)
272 if ( pDestination == pSource )
274 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
275 for( size_t count = 0; count < outSize; count += 4 )
277 #pragma warning(suppress: 6001 6101) // PREFast doesn't properly understand the aliasing here.
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);
285 *(dPtr++) = t1 | t2 | t3 | ta;
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 )
295 uint32_t t = *(sPtr++);
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);
302 *(dPtr++) = t1 | t2 | t3 | ta;
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 )
322 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
323 for( size_t count = 0; count < outSize; count += 4 )
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);
332 *(dPtr++) = t1 | t2 | t3 | ta;
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 )
342 uint32_t t = *(sPtr++);
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);
349 *(dPtr++) = t1 | t2 | t3 | ta;
355 // Fall-through case is to just use memcpy (assuming this is not an in-place operation)
356 if ( pDestination == pSource )
359 size_t size = std::min<size_t>( outSize, inSize );
360 memcpy_s( pDestination, outSize, pSource, size );
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 )
371 assert( pDestination && outSize > 0 );
372 assert( pSource && inSize > 0 );
373 assert( IsValid(outFormat) && !IsVideo(outFormat) );
374 assert( IsValid(inFormat) && !IsVideo(inFormat) );
378 case DXGI_FORMAT_B5G6R5_UNORM:
379 if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
382 // DXGI_FORMAT_B5G6R5_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
384 const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
385 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
387 for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
389 uint16_t t = *(sPtr++);
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);
395 *(dPtr++) = t1 | t2 | t3 | 0xff000000;
400 case DXGI_FORMAT_B5G5R5A1_UNORM:
401 if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
404 // DXGI_FORMAT_B5G5R5A1_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
406 const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
407 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
409 for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
411 uint16_t t = *(sPtr++);
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);
418 *(dPtr++) = t1 | t2 | t3 | ta;
423 #ifdef DXGI_1_2_FORMATS
424 case DXGI_FORMAT_B4G4R4A4_UNORM:
425 if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
428 // DXGI_FORMAT_B4G4R4A4_UNORM -> DXGI_FORMAT_R8G8B8A8_UNORM
430 const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
431 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
433 for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
435 uint16_t t = *(sPtr++);
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));
442 *(dPtr++) = t1 | t2 | t3 | ta;
446 #endif // DXGI_1_2_FORMATS
453 //-------------------------------------------------------------------------------------
454 // Loads an image row into standard RGBA XMVECTOR (aligned) array
455 //-------------------------------------------------------------------------------------
456 #define LOAD_SCANLINE( type, func )\
457 if ( size >= sizeof(type) )\
459 const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
460 for( size_t icount = 0; icount < size; icount += sizeof(type) )\
462 if ( dPtr >= ePtr ) break;\
463 *(dPtr++) = func( sPtr++ );\
469 #define LOAD_SCANLINE3( type, func, defvec )\
470 if ( size >= sizeof(type) )\
472 const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
473 for( size_t icount = 0; icount < size; icount += sizeof(type) )\
475 XMVECTOR v = func( sPtr++ );\
476 if ( dPtr >= ePtr ) break;\
477 *(dPtr++) = XMVectorSelect( defvec, v, g_XMSelect1110 );\
483 #define LOAD_SCANLINE2( type, func, defvec )\
484 if ( size >= sizeof(type) )\
486 const type * __restrict sPtr = reinterpret_cast<const type*>(pSource);\
487 for( size_t icount = 0; icount < size; icount += sizeof(type) )\
489 XMVECTOR v = func( sPtr++ );\
490 if ( dPtr >= ePtr ) break;\
491 *(dPtr++) = XMVectorSelect( defvec, v, g_XMSelect1100 );\
497 bool _LoadScanline( XMVECTOR* pDestination, size_t count,
498 LPCVOID pSource, size_t size, DXGI_FORMAT format )
500 #if !defined(_XM_NO_INTRINSICS_)
501 assert( pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0) );
503 assert( pSource && size > 0 );
504 assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
506 XMVECTOR* __restrict dPtr = pDestination;
510 const XMVECTOR* ePtr = pDestination + count;
514 case DXGI_FORMAT_R32G32B32A32_FLOAT:
516 size_t msize = (size > (sizeof(XMVECTOR)*count)) ? (sizeof(XMVECTOR)*count) : size;
517 memcpy_s( dPtr, sizeof(XMVECTOR)*count, pSource, msize );
521 case DXGI_FORMAT_R32G32B32A32_UINT:
522 LOAD_SCANLINE( XMUINT4, XMLoadUInt4 )
524 case DXGI_FORMAT_R32G32B32A32_SINT:
525 LOAD_SCANLINE( XMINT4, XMLoadSInt4 )
527 case DXGI_FORMAT_R32G32B32_FLOAT:
528 LOAD_SCANLINE3( XMFLOAT3, XMLoadFloat3, g_XMIdentityR3 )
530 case DXGI_FORMAT_R32G32B32_UINT:
531 LOAD_SCANLINE3( XMUINT3, XMLoadUInt3, g_XMIdentityR3 )
533 case DXGI_FORMAT_R32G32B32_SINT:
534 LOAD_SCANLINE3( XMINT3, XMLoadSInt3, g_XMIdentityR3 )
536 case DXGI_FORMAT_R16G16B16A16_FLOAT:
537 LOAD_SCANLINE( XMHALF4, XMLoadHalf4 )
539 case DXGI_FORMAT_R16G16B16A16_UNORM:
540 LOAD_SCANLINE( XMUSHORTN4, XMLoadUShortN4 )
542 case DXGI_FORMAT_R16G16B16A16_UINT:
543 LOAD_SCANLINE( XMUSHORT4, XMLoadUShort4 )
545 case DXGI_FORMAT_R16G16B16A16_SNORM:
546 LOAD_SCANLINE( XMSHORTN4, XMLoadShortN4 )
548 case DXGI_FORMAT_R16G16B16A16_SINT:
549 LOAD_SCANLINE( XMSHORT4, XMLoadShort4 )
551 case DXGI_FORMAT_R32G32_FLOAT:
552 LOAD_SCANLINE2( XMFLOAT2, XMLoadFloat2, g_XMIdentityR3 )
554 case DXGI_FORMAT_R32G32_UINT:
555 LOAD_SCANLINE2( XMUINT2, XMLoadUInt2, g_XMIdentityR3 )
557 case DXGI_FORMAT_R32G32_SINT:
558 LOAD_SCANLINE2( XMINT2, XMLoadSInt2, g_XMIdentityR3 )
560 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
561 if ( size >= (sizeof(float)+sizeof(uint32_t)) )
563 const float * sPtr = reinterpret_cast<const float*>(pSource);
564 for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
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 );
575 case DXGI_FORMAT_R10G10B10A2_UNORM:
576 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
577 LOAD_SCANLINE( XMUDECN4, XMLoadUDecN4 );
579 case DXGI_FORMAT_R10G10B10A2_UINT:
580 LOAD_SCANLINE( XMUDEC4, XMLoadUDec4 );
582 case DXGI_FORMAT_R11G11B10_FLOAT:
583 LOAD_SCANLINE3( XMFLOAT3PK, XMLoadFloat3PK, g_XMIdentityR3 );
585 case DXGI_FORMAT_R8G8B8A8_UNORM:
586 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
587 LOAD_SCANLINE( XMUBYTEN4, XMLoadUByteN4 )
589 case DXGI_FORMAT_R8G8B8A8_UINT:
590 LOAD_SCANLINE( XMUBYTE4, XMLoadUByte4 )
592 case DXGI_FORMAT_R8G8B8A8_SNORM:
593 LOAD_SCANLINE( XMBYTEN4, XMLoadByteN4 )
595 case DXGI_FORMAT_R8G8B8A8_SINT:
596 LOAD_SCANLINE( XMBYTE4, XMLoadByte4 )
598 case DXGI_FORMAT_R16G16_FLOAT:
599 LOAD_SCANLINE2( XMHALF2, XMLoadHalf2, g_XMIdentityR3 )
601 case DXGI_FORMAT_R16G16_UNORM:
602 LOAD_SCANLINE2( XMUSHORTN2, XMLoadUShortN2, g_XMIdentityR3 )
604 case DXGI_FORMAT_R16G16_UINT:
605 LOAD_SCANLINE2( XMUSHORT2, XMLoadUShort2, g_XMIdentityR3 )
607 case DXGI_FORMAT_R16G16_SNORM:
608 LOAD_SCANLINE2( XMSHORTN2, XMLoadShortN2, g_XMIdentityR3 )
610 case DXGI_FORMAT_R16G16_SINT:
611 LOAD_SCANLINE2( XMSHORT2, XMLoadShort2, g_XMIdentityR3 )
613 case DXGI_FORMAT_D32_FLOAT:
614 case DXGI_FORMAT_R32_FLOAT:
615 if ( size >= sizeof(float) )
617 const float* __restrict sPtr = reinterpret_cast<const float*>(pSource);
618 for( size_t icount = 0; icount < size; icount += sizeof(float) )
620 XMVECTOR v = XMLoadFloat( sPtr++ );
621 if ( dPtr >= ePtr ) break;
622 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
628 case DXGI_FORMAT_R32_UINT:
629 if ( size >= sizeof(uint32_t) )
631 const uint32_t* __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
632 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
634 XMVECTOR v = XMLoadInt( sPtr++ );
635 v = XMConvertVectorUIntToFloat( v, 0 );
636 if ( dPtr >= ePtr ) break;
637 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
643 case DXGI_FORMAT_R32_SINT:
644 if ( size >= sizeof(int32_t) )
646 const int32_t * __restrict sPtr = reinterpret_cast<const int32_t*>(pSource);
647 for( size_t icount = 0; icount < size; icount += sizeof(int32_t) )
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 );
658 case DXGI_FORMAT_D24_UNORM_S8_UINT:
659 if ( size >= sizeof(uint32_t) )
661 const uint32_t * sPtr = reinterpret_cast<const uint32_t*>(pSource);
662 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
664 float d = static_cast<float>( *sPtr & 0xFFFFFF ) / 16777215.f;
665 float s = static_cast<float>( ( *sPtr & 0xFF000000 ) >> 24 );
667 if ( dPtr >= ePtr ) break;
668 *(dPtr++) = XMVectorSet( d, s, 0.f, 1.f );
674 case DXGI_FORMAT_R8G8_UNORM:
675 LOAD_SCANLINE2( XMUBYTEN2, XMLoadUByteN2, g_XMIdentityR3 )
677 case DXGI_FORMAT_R8G8_UINT:
678 LOAD_SCANLINE2( XMUBYTE2, XMLoadUByte2, g_XMIdentityR3 )
680 case DXGI_FORMAT_R8G8_SNORM:
681 LOAD_SCANLINE2( XMBYTEN2, XMLoadByteN2, g_XMIdentityR3 )
683 case DXGI_FORMAT_R8G8_SINT:
684 LOAD_SCANLINE2( XMBYTE2, XMLoadByte2, g_XMIdentityR3 )
686 case DXGI_FORMAT_R16_FLOAT:
687 if ( size >= sizeof(HALF) )
689 const HALF * __restrict sPtr = reinterpret_cast<const HALF*>(pSource);
690 for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
692 if ( dPtr >= ePtr ) break;
693 *(dPtr++) = XMVectorSet( XMConvertHalfToFloat(*sPtr++), 0.f, 0.f, 1.f );
699 case DXGI_FORMAT_D16_UNORM:
700 case DXGI_FORMAT_R16_UNORM:
701 if ( size >= sizeof(uint16_t) )
703 const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
704 for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
706 if ( dPtr >= ePtr ) break;
707 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 65535.f, 0.f, 0.f, 1.f );
713 case DXGI_FORMAT_R16_UINT:
714 if ( size >= sizeof(uint16_t) )
716 const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
717 for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
719 if ( dPtr >= ePtr ) break;
720 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
726 case DXGI_FORMAT_R16_SNORM:
727 if ( size >= sizeof(int16_t) )
729 const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
730 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
732 if ( dPtr >= ePtr ) break;
733 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 32767.f, 0.f, 0.f, 1.f );
739 case DXGI_FORMAT_R16_SINT:
740 if ( size >= sizeof(int16_t) )
742 const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
743 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
745 if ( dPtr >= ePtr ) break;
746 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
752 case DXGI_FORMAT_R8_UNORM:
753 if ( size >= sizeof(uint8_t) )
755 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
756 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
758 if ( dPtr >= ePtr ) break;
759 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 255.f, 0.f, 0.f, 1.f );
765 case DXGI_FORMAT_R8_UINT:
766 if ( size >= sizeof(uint8_t) )
768 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
769 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
771 if ( dPtr >= ePtr ) break;
772 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
778 case DXGI_FORMAT_R8_SNORM:
779 if ( size >= sizeof(char) )
781 const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
782 for( size_t icount = 0; icount < size; icount += sizeof(char) )
784 if ( dPtr >= ePtr ) break;
785 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 127.f, 0.f, 0.f, 1.f );
791 case DXGI_FORMAT_R8_SINT:
792 if ( size >= sizeof(char) )
794 const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
795 for( size_t icount = 0; icount < size; icount += sizeof(char) )
797 if ( dPtr >= ePtr ) break;
798 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
804 case DXGI_FORMAT_A8_UNORM:
805 if ( size >= sizeof(uint8_t) )
807 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
808 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
810 if ( dPtr >= ePtr ) break;
811 *(dPtr++) = XMVectorSet( 0.f, 0.f, 0.f, static_cast<float>(*sPtr++) / 255.f );
817 case DXGI_FORMAT_R1_UNORM:
818 if ( size >= sizeof(uint8_t) )
820 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
821 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
823 for( size_t bcount = 0; bcount < 8; ++bcount )
825 if ( dPtr >= ePtr ) break;
826 *(dPtr++) = XMVectorSet( (((*sPtr >> bcount) & 0x1) ? 1.f : 0.f), 0.f, 0.f, 1.f );
835 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
836 LOAD_SCANLINE3( XMFLOAT3SE, XMLoadFloat3SE, g_XMIdentityR3 )
838 case DXGI_FORMAT_R8G8_B8G8_UNORM:
839 if ( size >= sizeof(XMUBYTEN4) )
841 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
842 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
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 );
855 case DXGI_FORMAT_G8R8_G8B8_UNORM:
856 if ( size >= sizeof(XMUBYTEN4) )
858 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
859 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
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 );
873 case DXGI_FORMAT_B5G6R5_UNORM:
874 if ( size >= sizeof(XMU565) )
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) )
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 );
890 case DXGI_FORMAT_B5G5R5A1_UNORM:
891 if ( size >= sizeof(XMU555) )
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) )
897 XMVECTOR v = XMLoadU555( sPtr++ );
898 v = XMVectorMultiply( v, s_Scale );
899 if ( dPtr >= ePtr ) break;
900 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
906 case DXGI_FORMAT_B8G8R8A8_UNORM:
907 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
908 if ( size >= sizeof(XMUBYTEN4) )
910 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
911 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
913 XMVECTOR v = XMLoadUByteN4( sPtr++ );
914 if ( dPtr >= ePtr ) break;
915 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
921 case DXGI_FORMAT_B8G8R8X8_UNORM:
922 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
923 if ( size >= sizeof(XMUBYTEN4) )
925 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
926 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
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 );
937 #ifdef DXGI_1_2_FORMATS
938 case DXGI_FORMAT_B4G4R4A4_UNORM:
939 if ( size >= sizeof(XMUNIBBLE4) )
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) )
945 XMVECTOR v = XMLoadUNibble4( sPtr++ );
946 v = XMVectorMultiply( v, s_Scale );
947 if ( dPtr >= ePtr ) break;
948 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
954 // we don't support the video formats ( see IsVideo function )
955 #endif // DXGI_1_2_FORMATS
963 //-------------------------------------------------------------------------------------
964 // Stores an image row from standard RGBA XMVECTOR (aligned) array
965 //-------------------------------------------------------------------------------------
966 #define STORE_SCANLINE( type, func )\
967 if ( size >= sizeof(type) )\
969 type * __restrict dPtr = reinterpret_cast<type*>(pDestination);\
970 for( size_t icount = 0; icount < size; icount += sizeof(type) )\
972 if ( sPtr >= ePtr ) break;\
973 func( dPtr++, *sPtr++ );\
978 bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
979 const XMVECTOR* pSource, size_t count )
981 assert( pDestination && size > 0 );
982 #if !defined(_XM_NO_INTRINSICS_)
983 assert( pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0) );
985 assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
987 const XMVECTOR* __restrict sPtr = pSource;
991 const XMVECTOR* ePtr = pSource + count;
995 case DXGI_FORMAT_R32G32B32A32_FLOAT:
996 STORE_SCANLINE( XMFLOAT4, XMStoreFloat4 )
998 case DXGI_FORMAT_R32G32B32A32_UINT:
999 STORE_SCANLINE( XMUINT4, XMStoreUInt4 )
1001 case DXGI_FORMAT_R32G32B32A32_SINT:
1002 STORE_SCANLINE( XMINT4, XMStoreSInt4 )
1004 case DXGI_FORMAT_R32G32B32_FLOAT:
1005 STORE_SCANLINE( XMFLOAT3, XMStoreFloat3 )
1007 case DXGI_FORMAT_R32G32B32_UINT:
1008 STORE_SCANLINE( XMUINT3, XMStoreUInt3 )
1010 case DXGI_FORMAT_R32G32B32_SINT:
1011 STORE_SCANLINE( XMINT3, XMStoreSInt3 )
1013 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1014 STORE_SCANLINE( XMHALF4, XMStoreHalf4 )
1016 case DXGI_FORMAT_R16G16B16A16_UNORM:
1017 STORE_SCANLINE( XMUSHORTN4, XMStoreUShortN4 )
1019 case DXGI_FORMAT_R16G16B16A16_UINT:
1020 STORE_SCANLINE( XMUSHORT4, XMStoreUShort4 )
1022 case DXGI_FORMAT_R16G16B16A16_SNORM:
1023 STORE_SCANLINE( XMSHORTN4, XMStoreShortN4 )
1025 case DXGI_FORMAT_R16G16B16A16_SINT:
1026 STORE_SCANLINE( XMSHORT4, XMStoreShort4 )
1028 case DXGI_FORMAT_R32G32_FLOAT:
1029 STORE_SCANLINE( XMFLOAT2, XMStoreFloat2 )
1031 case DXGI_FORMAT_R32G32_UINT:
1032 STORE_SCANLINE( XMUINT2, XMStoreUInt2 )
1034 case DXGI_FORMAT_R32G32_SINT:
1035 STORE_SCANLINE( XMINT2, XMStoreSInt2 )
1037 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
1038 if ( size >= (sizeof(float)+sizeof(uint32_t)) )
1040 float *dPtr = reinterpret_cast<float*>(pDestination);
1041 for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
1043 if ( sPtr >= ePtr ) break;
1045 XMStoreFloat4( &f, *sPtr++ );
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;
1055 case DXGI_FORMAT_R10G10B10A2_UNORM:
1056 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
1057 STORE_SCANLINE( XMUDECN4, XMStoreUDecN4 );
1059 case DXGI_FORMAT_R10G10B10A2_UINT:
1060 STORE_SCANLINE( XMUDEC4, XMStoreUDec4 );
1062 case DXGI_FORMAT_R11G11B10_FLOAT:
1063 STORE_SCANLINE( XMFLOAT3PK, XMStoreFloat3PK );
1065 case DXGI_FORMAT_R8G8B8A8_UNORM:
1066 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1067 STORE_SCANLINE( XMUBYTEN4, XMStoreUByteN4 )
1069 case DXGI_FORMAT_R8G8B8A8_UINT:
1070 STORE_SCANLINE( XMUBYTE4, XMStoreUByte4 )
1072 case DXGI_FORMAT_R8G8B8A8_SNORM:
1073 STORE_SCANLINE( XMBYTEN4, XMStoreByteN4 )
1075 case DXGI_FORMAT_R8G8B8A8_SINT:
1076 STORE_SCANLINE( XMBYTE4, XMStoreByte4 )
1078 case DXGI_FORMAT_R16G16_FLOAT:
1079 STORE_SCANLINE( XMHALF2, XMStoreHalf2 )
1081 case DXGI_FORMAT_R16G16_UNORM:
1082 STORE_SCANLINE( XMUSHORTN2, XMStoreUShortN2 )
1084 case DXGI_FORMAT_R16G16_UINT:
1085 STORE_SCANLINE( XMUSHORT2, XMStoreUShort2 )
1087 case DXGI_FORMAT_R16G16_SNORM:
1088 STORE_SCANLINE( XMSHORTN2, XMStoreShortN2 )
1090 case DXGI_FORMAT_R16G16_SINT:
1091 STORE_SCANLINE( XMSHORT2, XMStoreShort2 )
1093 case DXGI_FORMAT_D32_FLOAT:
1094 case DXGI_FORMAT_R32_FLOAT:
1095 if ( size >= sizeof(float) )
1097 float * __restrict dPtr = reinterpret_cast<float*>(pDestination);
1098 for( size_t icount = 0; icount < size; icount += sizeof(float) )
1100 if ( sPtr >= ePtr ) break;
1101 XMStoreFloat( dPtr++, *(sPtr++) );
1106 case DXGI_FORMAT_R32_UINT:
1107 if ( size >= sizeof(uint32_t) )
1109 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
1110 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1112 if ( sPtr >= ePtr ) break;
1113 XMVECTOR v = XMConvertVectorFloatToUInt( *(sPtr++), 0 );
1114 XMStoreInt( dPtr++, v );
1119 case DXGI_FORMAT_R32_SINT:
1120 if ( size >= sizeof(uint32_t) )
1122 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
1123 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1125 if ( sPtr >= ePtr ) break;
1126 XMVECTOR v = XMConvertVectorFloatToInt( *(sPtr++), 0 );
1127 XMStoreInt( dPtr++, v );
1132 case DXGI_FORMAT_D24_UNORM_S8_UINT:
1133 if ( size >= sizeof(uint32_t) )
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) )
1140 if ( sPtr >= ePtr ) break;
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);
1149 case DXGI_FORMAT_R8G8_UNORM:
1150 STORE_SCANLINE( XMUBYTEN2, XMStoreUByteN2 )
1152 case DXGI_FORMAT_R8G8_UINT:
1153 STORE_SCANLINE( XMUBYTE2, XMStoreUByte2 )
1155 case DXGI_FORMAT_R8G8_SNORM:
1156 STORE_SCANLINE( XMBYTEN2, XMStoreByteN2 )
1158 case DXGI_FORMAT_R8G8_SINT:
1159 STORE_SCANLINE( XMBYTE2, XMStoreByte2 )
1161 case DXGI_FORMAT_R16_FLOAT:
1162 if ( size >= sizeof(HALF) )
1164 HALF * __restrict dPtr = reinterpret_cast<HALF*>(pDestination);
1165 for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
1167 if ( sPtr >= ePtr ) break;
1168 float v = XMVectorGetX( *sPtr++ );
1169 *(dPtr++) = XMConvertFloatToHalf(v);
1174 case DXGI_FORMAT_D16_UNORM:
1175 case DXGI_FORMAT_R16_UNORM:
1176 if ( size >= sizeof(int16_t) )
1178 int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1179 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
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 );
1189 case DXGI_FORMAT_R16_UINT:
1190 if ( size >= sizeof(uint16_t) )
1192 uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
1193 for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
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);
1203 case DXGI_FORMAT_R16_SNORM:
1204 if ( size >= sizeof(int16_t) )
1206 int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1207 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
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 );
1217 case DXGI_FORMAT_R16_SINT:
1218 if ( size >= sizeof(int16_t) )
1220 int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1221 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
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);
1231 case DXGI_FORMAT_R8_UNORM:
1232 if ( size >= sizeof(uint8_t) )
1234 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1235 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
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);
1245 case DXGI_FORMAT_R8_UINT:
1246 if ( size >= sizeof(uint8_t) )
1248 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1249 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
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);
1259 case DXGI_FORMAT_R8_SNORM:
1260 if ( size >= sizeof(char) )
1262 char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
1263 for( size_t icount = 0; icount < size; icount += sizeof(char) )
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 );
1273 case DXGI_FORMAT_R8_SINT:
1274 if ( size >= sizeof(char) )
1276 char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
1277 for( size_t icount = 0; icount < size; icount += sizeof(char) )
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 );
1287 case DXGI_FORMAT_A8_UNORM:
1288 if ( size >= sizeof(uint8_t) )
1290 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1291 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
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);
1301 case DXGI_FORMAT_R1_UNORM:
1302 if ( size >= sizeof(uint8_t) )
1304 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1305 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1308 for( size_t bcount = 0; bcount < 8; ++bcount )
1310 if ( sPtr >= ePtr ) break;
1311 float v = XMVectorGetX( *sPtr++ );
1313 pixels |= 1 << bcount;
1320 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
1321 STORE_SCANLINE( XMFLOAT3SE, XMStoreFloat3SE )
1323 case DXGI_FORMAT_R8G8_B8G8_UNORM:
1324 if ( size >= sizeof(XMUBYTEN4) )
1326 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1327 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
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 );
1338 case DXGI_FORMAT_G8R8_G8B8_UNORM:
1339 if ( size >= sizeof(XMUBYTEN4) )
1341 static XMVECTORI32 select1101 = {XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1};
1343 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1344 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
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 );
1355 case DXGI_FORMAT_B5G6R5_UNORM:
1356 if ( size >= sizeof(XMU565) )
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) )
1362 if ( sPtr >= ePtr ) break;
1363 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1364 v = XMVectorMultiply( v, s_Scale );
1365 XMStoreU565( dPtr++, v );
1370 case DXGI_FORMAT_B5G5R5A1_UNORM:
1371 if ( size >= sizeof(XMU555) )
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) )
1377 if ( sPtr >= ePtr ) break;
1378 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1379 v = XMVectorMultiply( v, s_Scale );
1380 XMStoreU555( dPtr++, v );
1385 case DXGI_FORMAT_B8G8R8A8_UNORM:
1386 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1387 if ( size >= sizeof(XMUBYTEN4) )
1389 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1390 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1392 if ( sPtr >= ePtr ) break;
1393 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1394 XMStoreUByteN4( dPtr++, v );
1399 case DXGI_FORMAT_B8G8R8X8_UNORM:
1400 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
1401 if ( size >= sizeof(XMUBYTEN4) )
1403 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1404 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1406 if ( sPtr >= ePtr ) break;
1407 XMVECTOR v = XMVectorPermute<2, 1, 0, 7>( *sPtr++, g_XMIdentityR3 );
1408 XMStoreUByteN4( dPtr++, v );
1413 #ifdef DXGI_1_2_FORMATS
1414 case DXGI_FORMAT_B4G4R4A4_UNORM:
1415 if ( size >= sizeof(XMUNIBBLE4) )
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) )
1421 if ( sPtr >= ePtr ) break;
1422 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1423 v = XMVectorMultiply( v, s_Scale );
1424 XMStoreUNibble4( dPtr++, v );
1429 // We don't support the video formats ( see IsVideo function )
1430 #endif // DXGI_1_2_FORMATS
1438 //-------------------------------------------------------------------------------------
1439 // Convert DXGI image to/from GUID_WICPixelFormat128bppRGBAFloat (no range conversions)
1440 //-------------------------------------------------------------------------------------
1441 HRESULT _ConvertToR32G32B32A32( const Image& srcImage, ScratchImage& image )
1443 if ( !srcImage.pixels )
1446 HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
1450 const Image *img = image.GetImage( 0, 0, 0 );
1457 uint8_t* pDest = img->pixels;
1464 const uint8_t *pSrc = srcImage.pixels;
1465 for( size_t h = 0; h < srcImage.height; ++h )
1467 if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
1473 pSrc += srcImage.rowPitch;
1474 pDest += img->rowPitch;
1480 HRESULT _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage )
1482 assert( srcImage.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1484 if ( !srcImage.pixels || !destImage.pixels )
1487 if ( srcImage.width != destImage.width || srcImage.height != destImage.height )
1490 const uint8_t *pSrc = srcImage.pixels;
1491 uint8_t* pDest = destImage.pixels;
1493 for( size_t h = 0; h < srcImage.height; ++h )
1495 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
1498 pSrc += srcImage.rowPitch;
1499 pDest += destImage.rowPitch;
1505 HRESULT _ConvertFromR32G32B32A32( const Image& srcImage, DXGI_FORMAT format, ScratchImage& image )
1507 if ( !srcImage.pixels )
1510 HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
1514 const Image *img = image.GetImage( 0, 0, 0 );
1521 hr = _ConvertFromR32G32B32A32( srcImage, *img );
1531 HRESULT _ConvertFromR32G32B32A32( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, ScratchImage& result )
1538 assert( metadata.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1540 TexMetadata mdata2 = metadata;
1541 mdata2.format = format;
1542 HRESULT hr = result.Initialize( mdata2 );
1546 if ( nimages != result.GetImageCount() )
1552 const Image* dest = result.GetImages();
1559 for( size_t index=0; index < nimages; ++index )
1561 const Image& src = srcImages[ index ];
1562 const Image& dst = dest[ index ];
1564 assert( src.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1565 assert( dst.format == format );
1567 if ( src.width != dst.width || src.height != dst.height )
1573 const uint8_t* pSrc = src.pixels;
1574 uint8_t* pDest = dst.pixels;
1575 if ( !pSrc || !pDest )
1581 for( size_t h=0; h < src.height; ++h )
1583 if ( !_StoreScanline( pDest, dst.rowPitch, format, reinterpret_cast<const XMVECTOR*>(pSrc), src.width ) )
1589 pSrc += src.rowPitch;
1590 pDest += dst.rowPitch;
1598 //-------------------------------------------------------------------------------------
1600 //-------------------------------------------------------------------------------------
1601 static const uint32_t g_fEncodeGamma22[] =
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
1637 #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
1638 static inline XMVECTOR _TableEncodeGamma22( FXMVECTOR v )
1641 XMStoreFloat4( (XMFLOAT4*)f, v );
1643 for( size_t i=0; i < 4; ++i )
1645 float f2 = sqrtf(f[i]) * 254.0f;
1647 uint32_t i2 = static_cast<uint32_t>(f2);
1648 i2 = std::min<uint32_t>( i2, _countof( g_fEncodeGamma22 )-2 );
1650 float fS = f2 - (float) i2;
1651 float fA = ((float *) g_fEncodeGamma22)[i2];
1652 float fB = ((float *) g_fEncodeGamma22)[i2 + 1];
1654 f[i] = fA + fS * (fB - fA);
1657 return XMLoadFloat4( (XMFLOAT4*)f );
1661 //-------------------------------------------------------------------------------------
1663 //-------------------------------------------------------------------------------------
1664 static const uint32_t g_fDecodeGamma22[] =
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
1701 #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
1702 static inline XMVECTOR _TableDecodeGamma22( FXMVECTOR v )
1705 XMStoreFloat4( (XMFLOAT4*)f, v );
1707 for( size_t i=0; i < 4; ++i )
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 );
1713 float fS = f2 - (float) i2;
1714 float fA = ((float *) g_fDecodeGamma22)[i2];
1715 float fB = ((float *) g_fDecodeGamma22)[i2 + 1];
1717 f[i] = fA + fS * (fB - fA);
1720 return XMLoadFloat4( (XMFLOAT4*)f );
1724 //-------------------------------------------------------------------------------------
1725 // Convert scanline based on source/target formats
1726 //-------------------------------------------------------------------------------------
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 },
1813 #pragma prefast( suppress : 25004, "Signature must match bsearch" );
1814 static int __cdecl _ConvertCompare( const void* ptr1, const void *ptr2 )
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;
1822 DWORD _GetConvertFlags( DXGI_FORMAT format )
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 )
1830 assert( g_ConvertTable[index].format > lastvalue );
1831 lastvalue = g_ConvertTable[index].format;
1835 ConvertData key = { format, 0 };
1836 const ConvertData* in = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1838 return (in) ? in->flags : 0;
1841 void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, DXGI_FORMAT inFormat, DWORD flags )
1843 #if !defined(_XM_NO_INTRINSICS_)
1844 assert( pBuffer && count > 0 && (((uintptr_t)pBuffer & 0xF) == 0) );
1846 assert( IsValid(outFormat) && !IsVideo(outFormat) && !IsTypeless(outFormat) );
1847 assert( IsValid(inFormat) && !IsVideo(inFormat) && !IsTypeless(inFormat) );
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 )
1858 assert( g_ConvertTable[index].format > lastvalue );
1859 lastvalue = g_ConvertTable[index].format;
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),
1867 key.format = outFormat;
1868 const ConvertData* out = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1876 assert( _GetConvertFlags( inFormat ) == in->flags );
1877 assert( _GetConvertFlags( outFormat ) == out->flags );
1879 // Handle SRGB filtering modes
1880 if ( IsSRGB( inFormat ) )
1881 flags |= TEX_FILTER_SRGB_IN;
1883 if ( IsSRGB( outFormat ) )
1884 flags |= TEX_FILTER_SRGB_OUT;
1886 if ( in->flags & CONVF_SNORM )
1887 flags &= ~TEX_FILTER_SRGB_IN;
1889 if ( out->flags & CONVF_SNORM )
1890 flags &= ~TEX_FILTER_SRGB_OUT;
1892 if ( (flags & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
1894 flags &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
1897 // sRGB input processing (sRGB -> RGB)
1898 if ( flags & TEX_FILTER_SRGB_IN )
1900 if ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) )
1902 XMVECTOR* ptr = pBuffer;
1903 for( size_t i=0; i < count; ++i )
1905 // rgb = rgb^(2.2); a=a
1907 XMVECTOR v1 = _TableDecodeGamma22( v );
1908 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
1913 // Handle conversion special cases
1914 DWORD diffFlags = in->flags ^ out->flags;
1915 if ( diffFlags != 0)
1917 if ( out->flags & CONVF_UNORM )
1919 if ( in->flags & CONVF_SNORM )
1922 XMVECTOR* ptr = pBuffer;
1923 for( size_t i=0; i < count; ++i )
1926 *ptr++ = XMVectorMultiplyAdd( v, g_XMOneHalf, g_XMOneHalf );
1929 else if ( in->flags & CONVF_FLOAT )
1932 XMVECTOR* ptr = pBuffer;
1933 for( size_t i=0; i < count; ++i )
1936 *ptr++ = XMVectorSaturate( v );
1940 else if ( out->flags & CONVF_SNORM )
1942 if ( in->flags & CONVF_UNORM )
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 )
1950 *ptr++ = XMVectorMultiplyAdd( v, two, g_XMNegativeOne );
1953 else if ( in->flags & CONVF_FLOAT )
1956 XMVECTOR* ptr = pBuffer;
1957 for( size_t i=0; i < count; ++i )
1960 *ptr++ = XMVectorClamp( v, g_XMNegativeOne, g_XMOne );
1965 // !CONVF_A -> CONVF_A is handled because LoadScanline ensures alpha defaults to 1.0 for no-alpha formats
1967 // CONVF_PACKED cases are handled because LoadScanline/StoreScanline handles packing/unpacking
1969 if ( ((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A) )
1971 // !CONVF_A -> A format
1972 XMVECTOR* ptr = pBuffer;
1973 for( size_t i=0; i < count; ++i )
1976 *ptr++ = XMVectorSplatX( v );
1979 else if ( ((in->flags & CONVF_RGBA_MASK) == CONVF_A) && !(out->flags & CONVF_A) )
1981 // A format -> !CONVF_A
1982 XMVECTOR* ptr = pBuffer;
1983 for( size_t i=0; i < count; ++i )
1986 *ptr++ = XMVectorSplatW( v );
1989 else if ( ((in->flags & CONVF_RGB_MASK) == CONVF_R) && ((out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B)) )
1991 // R format -> RGB format
1992 XMVECTOR* ptr = pBuffer;
1993 for( size_t i=0; i < count; ++i )
1996 XMVECTOR v1 = XMVectorSplatX( v );
1997 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
2002 // sRGB output processing (RGB -> sRGB)
2003 if ( flags & TEX_FILTER_SRGB_OUT )
2005 if ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) )
2007 XMVECTOR* ptr = pBuffer;
2008 for( size_t i=0; i < count; ++i )
2010 // rgb = rgb^(1/2.2); a=a
2012 XMVECTOR v1 = _TableEncodeGamma22( v );
2013 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
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 )
2027 assert( srcImage.width == destImage.width );
2028 assert( srcImage.height == destImage.height );
2030 IWICImagingFactory* pWIC = _GetWIC();
2032 return E_NOINTERFACE;
2034 ScopedObject<IWICFormatConverter> FC;
2035 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2039 // Need to implement usage of TEX_FILTER_SRGB_IN/TEX_FILTER_SRGB_OUT
2041 BOOL canConvert = FALSE;
2042 hr = FC->CanConvert( pfGUID, targetGUID, &canConvert );
2043 if ( FAILED(hr) || !canConvert )
2045 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2046 return E_UNEXPECTED;
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 );
2056 hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2060 hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
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 )
2074 assert( srcImage.width == destImage.width );
2075 assert( srcImage.height == destImage.height );
2077 IWICImagingFactory* pWIC = _GetWIC();
2079 return E_NOINTERFACE;
2081 ScopedObject<IWICFormatConverter> FC;
2082 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2086 BOOL canConvert = FALSE;
2087 hr = FC->CanConvert( pfGUID, GUID_WICPixelFormat128bppRGBAFloat, &canConvert );
2088 if ( FAILED(hr) || !canConvert )
2090 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2091 return E_UNEXPECTED;
2095 hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2099 const Image *timg = temp.GetImage( 0, 0, 0 );
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 );
2110 hr = FC->Initialize( source.Get(), GUID_WICPixelFormat128bppRGBAFloat, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2114 hr = FC->CopyPixels( 0, static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ), timg->pixels );
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 )
2124 for( size_t h = 0; h < srcImage.height; ++h )
2126 _ConvertScanline( reinterpret_cast<XMVECTOR*>(pSrc), srcImage.width, destImage.format, DXGI_FORMAT_R32G32B32A32_FLOAT, filter );
2128 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
2131 pSrc += timg->rowPitch;
2132 pDest += destImage.rowPitch;
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 )
2145 assert( srcImage.width == destImage.width );
2146 assert( srcImage.height == destImage.height );
2148 IWICImagingFactory* pWIC = _GetWIC();
2150 return E_NOINTERFACE;
2152 ScopedObject<IWICFormatConverter> FC;
2153 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2157 BOOL canConvert = FALSE;
2158 hr = FC->CanConvert( GUID_WICPixelFormat128bppRGBAFloat, targetGUID, &canConvert );
2159 if ( FAILED(hr) || !canConvert )
2161 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2162 return E_UNEXPECTED;
2166 hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2170 const Image *timg = temp.GetImage( 0, 0, 0 );
2174 const uint8_t *pSrc = srcImage.pixels;
2178 uint8_t *pDest = timg->pixels;
2182 for( size_t h = 0; h < srcImage.height; ++h )
2184 if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2187 _ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
2189 pSrc += srcImage.rowPitch;
2190 pDest += timg->rowPitch;
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 );
2201 hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2205 hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
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 )
2218 assert( srcImage.width == destImage.width );
2219 assert( srcImage.height == destImage.height );
2221 ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
2223 return E_OUTOFMEMORY;
2225 const uint8_t *pSrc = srcImage.pixels;
2226 uint8_t *pDest = destImage.pixels;
2227 if ( !pSrc || !pDest )
2230 for( size_t h = 0; h < srcImage.height; ++h )
2232 if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2235 _ConvertScanline( scanline.get(), srcImage.width, destImage.format, srcImage.format, filter );
2237 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
2240 pSrc += srcImage.rowPitch;
2241 pDest += destImage.rowPitch;
2248 //=====================================================================================
2250 //=====================================================================================
2252 //-------------------------------------------------------------------------------------
2254 //-------------------------------------------------------------------------------------
2255 HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& image )
2257 if ( (srcImage.format == format) || !IsValid( format ) )
2258 return E_INVALIDARG;
2260 if ( !srcImage.pixels )
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 );
2269 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
2270 return E_INVALIDARG;
2273 HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
2277 const Image *rimage = image.GetImage( 0, 0, 0 );
2284 WICPixelFormatGUID pfGUID;
2285 if ( _DXGIToWIC( srcImage.format, pfGUID ) )
2287 WICPixelFormatGUID targetGUID;
2288 if ( _DXGIToWIC( format, targetGUID ) )
2290 // Case 1: Both source and target formats are WIC supported
2291 hr = _ConvertUsingWIC( srcImage, pfGUID, targetGUID, filter, threshold, *rimage );
2295 // Case 2: Source format is supported by WIC, but not the target format
2296 hr = _ConvertFromWIC( srcImage, pfGUID, filter, threshold, *rimage );
2301 WICPixelFormatGUID targetGUID;
2302 if ( _DXGIToWIC( format, targetGUID ) )
2304 // Case 3: Source format is not supported by WIC, but does support the target format
2305 hr = _ConvertToWIC( srcImage, targetGUID, filter, threshold, *rimage );
2309 // Case 4: Both source and target format are not supported by WIC
2310 hr = _Convert( srcImage, filter, *rimage );
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 )
2330 if ( !srcImages || !nimages || (metadata.format == format) || !IsValid(format) )
2331 return E_INVALIDARG;
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 );
2339 if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
2340 return E_INVALIDARG;
2343 TexMetadata mdata2 = metadata;
2344 mdata2.format = format;
2345 HRESULT hr = result.Initialize( mdata2 );
2349 if ( nimages != result.GetImageCount() )
2355 const Image* dest = result.GetImages();
2362 WICPixelFormatGUID pfGUID, targetGUID;
2363 bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
2364 bool wictargetpf = _DXGIToWIC( format, targetGUID );
2366 for( size_t index=0; index < nimages; ++index )
2368 const Image& src = srcImages[ index ];
2369 if ( src.format != metadata.format )
2376 if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
2380 const Image& dst = dest[ index ];
2381 assert( dst.format == format );
2383 if ( src.width != dst.width || src.height != dst.height )
2393 // Case 1: Both source and target formats are WIC supported
2394 hr = _ConvertUsingWIC( src, pfGUID, targetGUID, filter, threshold, dst );
2398 // Case 2: Source format is supported by WIC, but not the target format
2399 hr = _ConvertFromWIC( src, pfGUID, filter, threshold, dst );
2406 // Case 3: Source format is not supported by WIC, but does support the target format
2407 hr = _ConvertToWIC( src, targetGUID, filter, threshold, dst );
2411 // Case 4: Both source and target format are not supported by WIC
2412 hr = _Convert( src, filter, dst );