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 assert( pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0) );
501 assert( pSource && size > 0 );
502 assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
504 XMVECTOR* __restrict dPtr = pDestination;
508 const XMVECTOR* ePtr = pDestination + count;
512 case DXGI_FORMAT_R32G32B32A32_FLOAT:
514 size_t msize = (size > (sizeof(XMVECTOR)*count)) ? (sizeof(XMVECTOR)*count) : size;
515 memcpy_s( dPtr, sizeof(XMVECTOR)*count, pSource, msize );
519 case DXGI_FORMAT_R32G32B32A32_UINT:
520 LOAD_SCANLINE( XMUINT4, XMLoadUInt4 )
522 case DXGI_FORMAT_R32G32B32A32_SINT:
523 LOAD_SCANLINE( XMINT4, XMLoadSInt4 )
525 case DXGI_FORMAT_R32G32B32_FLOAT:
526 LOAD_SCANLINE3( XMFLOAT3, XMLoadFloat3, g_XMIdentityR3 )
528 case DXGI_FORMAT_R32G32B32_UINT:
529 LOAD_SCANLINE3( XMUINT3, XMLoadUInt3, g_XMIdentityR3 )
531 case DXGI_FORMAT_R32G32B32_SINT:
532 LOAD_SCANLINE3( XMINT3, XMLoadSInt3, g_XMIdentityR3 )
534 case DXGI_FORMAT_R16G16B16A16_FLOAT:
535 LOAD_SCANLINE( XMHALF4, XMLoadHalf4 )
537 case DXGI_FORMAT_R16G16B16A16_UNORM:
538 LOAD_SCANLINE( XMUSHORTN4, XMLoadUShortN4 )
540 case DXGI_FORMAT_R16G16B16A16_UINT:
541 LOAD_SCANLINE( XMUSHORT4, XMLoadUShort4 )
543 case DXGI_FORMAT_R16G16B16A16_SNORM:
544 LOAD_SCANLINE( XMSHORTN4, XMLoadShortN4 )
546 case DXGI_FORMAT_R16G16B16A16_SINT:
547 LOAD_SCANLINE( XMSHORT4, XMLoadShort4 )
549 case DXGI_FORMAT_R32G32_FLOAT:
550 LOAD_SCANLINE2( XMFLOAT2, XMLoadFloat2, g_XMIdentityR3 )
552 case DXGI_FORMAT_R32G32_UINT:
553 LOAD_SCANLINE2( XMUINT2, XMLoadUInt2, g_XMIdentityR3 )
555 case DXGI_FORMAT_R32G32_SINT:
556 LOAD_SCANLINE2( XMINT2, XMLoadSInt2, g_XMIdentityR3 )
558 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
559 if ( size >= (sizeof(float)+sizeof(uint32_t)) )
561 const float * sPtr = reinterpret_cast<const float*>(pSource);
562 for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
564 const uint8_t* ps8 = reinterpret_cast<const uint8_t*>( &sPtr[1] );
565 if ( dPtr >= ePtr ) break;
566 *(dPtr++) = XMVectorSet( sPtr[0], static_cast<float>( *ps8 ), 0.f, 1.f );
573 case DXGI_FORMAT_R10G10B10A2_UNORM:
574 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
575 LOAD_SCANLINE( XMUDECN4, XMLoadUDecN4 );
577 case DXGI_FORMAT_R10G10B10A2_UINT:
578 LOAD_SCANLINE( XMUDEC4, XMLoadUDec4 );
580 case DXGI_FORMAT_R11G11B10_FLOAT:
581 LOAD_SCANLINE3( XMFLOAT3PK, XMLoadFloat3PK, g_XMIdentityR3 );
583 case DXGI_FORMAT_R8G8B8A8_UNORM:
584 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
585 LOAD_SCANLINE( XMUBYTEN4, XMLoadUByteN4 )
587 case DXGI_FORMAT_R8G8B8A8_UINT:
588 LOAD_SCANLINE( XMUBYTE4, XMLoadUByte4 )
590 case DXGI_FORMAT_R8G8B8A8_SNORM:
591 LOAD_SCANLINE( XMBYTEN4, XMLoadByteN4 )
593 case DXGI_FORMAT_R8G8B8A8_SINT:
594 LOAD_SCANLINE( XMBYTE4, XMLoadByte4 )
596 case DXGI_FORMAT_R16G16_FLOAT:
597 LOAD_SCANLINE2( XMHALF2, XMLoadHalf2, g_XMIdentityR3 )
599 case DXGI_FORMAT_R16G16_UNORM:
600 LOAD_SCANLINE2( XMUSHORTN2, XMLoadUShortN2, g_XMIdentityR3 )
602 case DXGI_FORMAT_R16G16_UINT:
603 LOAD_SCANLINE2( XMUSHORT2, XMLoadUShort2, g_XMIdentityR3 )
605 case DXGI_FORMAT_R16G16_SNORM:
606 LOAD_SCANLINE2( XMSHORTN2, XMLoadShortN2, g_XMIdentityR3 )
608 case DXGI_FORMAT_R16G16_SINT:
609 LOAD_SCANLINE2( XMSHORT2, XMLoadShort2, g_XMIdentityR3 )
611 case DXGI_FORMAT_D32_FLOAT:
612 case DXGI_FORMAT_R32_FLOAT:
613 if ( size >= sizeof(float) )
615 const float* __restrict sPtr = reinterpret_cast<const float*>(pSource);
616 for( size_t icount = 0; icount < size; icount += sizeof(float) )
618 XMVECTOR v = XMLoadFloat( sPtr++ );
619 if ( dPtr >= ePtr ) break;
620 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
626 case DXGI_FORMAT_R32_UINT:
627 if ( size >= sizeof(uint32_t) )
629 const uint32_t* __restrict sPtr = reinterpret_cast<const uint32_t*>(pSource);
630 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
632 XMVECTOR v = XMLoadInt( sPtr++ );
633 v = XMConvertVectorUIntToFloat( v, 0 );
634 if ( dPtr >= ePtr ) break;
635 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
641 case DXGI_FORMAT_R32_SINT:
642 if ( size >= sizeof(int32_t) )
644 const int32_t * __restrict sPtr = reinterpret_cast<const int32_t*>(pSource);
645 for( size_t icount = 0; icount < size; icount += sizeof(int32_t) )
647 XMVECTOR v = XMLoadInt( reinterpret_cast<const uint32_t*> (sPtr++) );
648 v = XMConvertVectorIntToFloat( v, 0 );
649 if ( dPtr >= ePtr ) break;
650 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1000 );
656 case DXGI_FORMAT_D24_UNORM_S8_UINT:
657 if ( size >= sizeof(uint32_t) )
659 const uint32_t * sPtr = reinterpret_cast<const uint32_t*>(pSource);
660 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
662 float d = static_cast<float>( *sPtr & 0xFFFFFF ) / 16777215.f;
663 float s = static_cast<float>( ( *sPtr & 0xFF000000 ) >> 24 );
665 if ( dPtr >= ePtr ) break;
666 *(dPtr++) = XMVectorSet( d, s, 0.f, 1.f );
672 case DXGI_FORMAT_R8G8_UNORM:
673 LOAD_SCANLINE2( XMUBYTEN2, XMLoadUByteN2, g_XMIdentityR3 )
675 case DXGI_FORMAT_R8G8_UINT:
676 LOAD_SCANLINE2( XMUBYTE2, XMLoadUByte2, g_XMIdentityR3 )
678 case DXGI_FORMAT_R8G8_SNORM:
679 LOAD_SCANLINE2( XMBYTEN2, XMLoadByteN2, g_XMIdentityR3 )
681 case DXGI_FORMAT_R8G8_SINT:
682 LOAD_SCANLINE2( XMBYTE2, XMLoadByte2, g_XMIdentityR3 )
684 case DXGI_FORMAT_R16_FLOAT:
685 if ( size >= sizeof(HALF) )
687 const HALF * __restrict sPtr = reinterpret_cast<const HALF*>(pSource);
688 for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
690 if ( dPtr >= ePtr ) break;
691 *(dPtr++) = XMVectorSet( XMConvertHalfToFloat(*sPtr++), 0.f, 0.f, 1.f );
697 case DXGI_FORMAT_D16_UNORM:
698 case DXGI_FORMAT_R16_UNORM:
699 if ( size >= sizeof(uint16_t) )
701 const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
702 for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
704 if ( dPtr >= ePtr ) break;
705 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 65535.f, 0.f, 0.f, 1.f );
711 case DXGI_FORMAT_R16_UINT:
712 if ( size >= sizeof(uint16_t) )
714 const uint16_t * __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
715 for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
717 if ( dPtr >= ePtr ) break;
718 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
724 case DXGI_FORMAT_R16_SNORM:
725 if ( size >= sizeof(int16_t) )
727 const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
728 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
730 if ( dPtr >= ePtr ) break;
731 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 32767.f, 0.f, 0.f, 1.f );
737 case DXGI_FORMAT_R16_SINT:
738 if ( size >= sizeof(int16_t) )
740 const int16_t * __restrict sPtr = reinterpret_cast<const int16_t*>(pSource);
741 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
743 if ( dPtr >= ePtr ) break;
744 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
750 case DXGI_FORMAT_R8_UNORM:
751 if ( size >= sizeof(uint8_t) )
753 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
754 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
756 if ( dPtr >= ePtr ) break;
757 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 255.f, 0.f, 0.f, 1.f );
763 case DXGI_FORMAT_R8_UINT:
764 if ( size >= sizeof(uint8_t) )
766 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
767 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
769 if ( dPtr >= ePtr ) break;
770 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
776 case DXGI_FORMAT_R8_SNORM:
777 if ( size >= sizeof(char) )
779 const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
780 for( size_t icount = 0; icount < size; icount += sizeof(char) )
782 if ( dPtr >= ePtr ) break;
783 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++) / 127.f, 0.f, 0.f, 1.f );
789 case DXGI_FORMAT_R8_SINT:
790 if ( size >= sizeof(char) )
792 const char * __restrict sPtr = reinterpret_cast<const char*>(pSource);
793 for( size_t icount = 0; icount < size; icount += sizeof(char) )
795 if ( dPtr >= ePtr ) break;
796 *(dPtr++) = XMVectorSet( static_cast<float>(*sPtr++), 0.f, 0.f, 1.f );
802 case DXGI_FORMAT_A8_UNORM:
803 if ( size >= sizeof(uint8_t) )
805 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
806 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
808 if ( dPtr >= ePtr ) break;
809 *(dPtr++) = XMVectorSet( 0.f, 0.f, 0.f, static_cast<float>(*sPtr++) / 255.f );
815 case DXGI_FORMAT_R1_UNORM:
816 if ( size >= sizeof(uint8_t) )
818 const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
819 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
821 for( size_t bcount = 0; bcount < 8; ++bcount )
823 if ( dPtr >= ePtr ) break;
824 *(dPtr++) = XMVectorSet( (((*sPtr >> bcount) & 0x1) ? 1.f : 0.f), 0.f, 0.f, 1.f );
833 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
834 LOAD_SCANLINE3( XMFLOAT3SE, XMLoadFloat3SE, g_XMIdentityR3 )
836 case DXGI_FORMAT_R8G8_B8G8_UNORM:
837 if ( size >= sizeof(XMUBYTEN4) )
839 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
840 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
842 XMVECTOR v = XMLoadUByteN4( sPtr++ );
843 XMVECTOR v1 = XMVectorSwizzle<0, 3, 2, 1>( v );
844 if ( dPtr >= ePtr ) break;
845 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1110 );
846 if ( dPtr >= ePtr ) break;
847 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v1, g_XMSelect1110 );
853 case DXGI_FORMAT_G8R8_G8B8_UNORM:
854 if ( size >= sizeof(XMUBYTEN4) )
856 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
857 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
859 XMVECTOR v = XMLoadUByteN4( sPtr++ );
860 XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>( v );
861 XMVECTOR v1 = XMVectorSwizzle<1, 2, 3, 0>( v );
862 if ( dPtr >= ePtr ) break;
863 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v0, g_XMSelect1110 );
864 if ( dPtr >= ePtr ) break;
865 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v1, g_XMSelect1110 );
871 case DXGI_FORMAT_B5G6R5_UNORM:
872 if ( size >= sizeof(XMU565) )
874 static XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/63.f, 1.f/31.f, 1.f };
875 const XMU565 * __restrict sPtr = reinterpret_cast<const XMU565*>(pSource);
876 for( size_t icount = 0; icount < size; icount += sizeof(XMU565) )
878 XMVECTOR v = XMLoadU565( sPtr++ );
879 v = XMVectorMultiply( v, s_Scale );
880 v = XMVectorSwizzle<2, 1, 0, 3>( v );
881 if ( dPtr >= ePtr ) break;
882 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1110 );
888 case DXGI_FORMAT_B5G5R5A1_UNORM:
889 if ( size >= sizeof(XMU555) )
891 static XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/31.f, 1.f/31.f, 1.f };
892 const XMU555 * __restrict sPtr = reinterpret_cast<const XMU555*>(pSource);
893 for( size_t icount = 0; icount < size; icount += sizeof(XMU555) )
895 XMVECTOR v = XMLoadU555( sPtr++ );
896 v = XMVectorMultiply( v, s_Scale );
897 if ( dPtr >= ePtr ) break;
898 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
904 case DXGI_FORMAT_B8G8R8A8_UNORM:
905 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
906 if ( size >= sizeof(XMUBYTEN4) )
908 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
909 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
911 XMVECTOR v = XMLoadUByteN4( sPtr++ );
912 if ( dPtr >= ePtr ) break;
913 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
919 case DXGI_FORMAT_B8G8R8X8_UNORM:
920 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
921 if ( size >= sizeof(XMUBYTEN4) )
923 const XMUBYTEN4 * __restrict sPtr = reinterpret_cast<const XMUBYTEN4*>(pSource);
924 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
926 XMVECTOR v = XMLoadUByteN4( sPtr++ );
927 v = XMVectorSwizzle<2, 1, 0, 3>( v );
928 if ( dPtr >= ePtr ) break;
929 *(dPtr++) = XMVectorSelect( g_XMIdentityR3, v, g_XMSelect1110 );
935 #ifdef DXGI_1_2_FORMATS
936 case DXGI_FORMAT_B4G4R4A4_UNORM:
937 if ( size >= sizeof(XMUNIBBLE4) )
939 static XMVECTORF32 s_Scale = { 1.f/15.f, 1.f/15.f, 1.f/15.f, 1.f/15.f };
940 const XMUNIBBLE4 * __restrict sPtr = reinterpret_cast<const XMUNIBBLE4*>(pSource);
941 for( size_t icount = 0; icount < size; icount += sizeof(XMUNIBBLE4) )
943 XMVECTOR v = XMLoadUNibble4( sPtr++ );
944 v = XMVectorMultiply( v, s_Scale );
945 if ( dPtr >= ePtr ) break;
946 *(dPtr++) = XMVectorSwizzle<2, 1, 0, 3>( v );
952 // we don't support the video formats ( see IsVideo function )
953 #endif // DXGI_1_2_FORMATS
961 //-------------------------------------------------------------------------------------
962 // Stores an image row from standard RGBA XMVECTOR (aligned) array
963 //-------------------------------------------------------------------------------------
964 #define STORE_SCANLINE( type, func )\
965 if ( size >= sizeof(type) )\
967 type * __restrict dPtr = reinterpret_cast<type*>(pDestination);\
968 for( size_t icount = 0; icount < size; icount += sizeof(type) )\
970 if ( sPtr >= ePtr ) break;\
971 func( dPtr++, *sPtr++ );\
976 bool _StoreScanline( LPVOID pDestination, size_t size, DXGI_FORMAT format,
977 const XMVECTOR* pSource, size_t count )
979 assert( pDestination && size > 0 );
980 assert( pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0) );
981 assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) );
983 const XMVECTOR* __restrict sPtr = pSource;
987 const XMVECTOR* ePtr = pSource + count;
991 case DXGI_FORMAT_R32G32B32A32_FLOAT:
992 STORE_SCANLINE( XMFLOAT4, XMStoreFloat4 )
994 case DXGI_FORMAT_R32G32B32A32_UINT:
995 STORE_SCANLINE( XMUINT4, XMStoreUInt4 )
997 case DXGI_FORMAT_R32G32B32A32_SINT:
998 STORE_SCANLINE( XMINT4, XMStoreSInt4 )
1000 case DXGI_FORMAT_R32G32B32_FLOAT:
1001 STORE_SCANLINE( XMFLOAT3, XMStoreFloat3 )
1003 case DXGI_FORMAT_R32G32B32_UINT:
1004 STORE_SCANLINE( XMUINT3, XMStoreUInt3 )
1006 case DXGI_FORMAT_R32G32B32_SINT:
1007 STORE_SCANLINE( XMINT3, XMStoreSInt3 )
1009 case DXGI_FORMAT_R16G16B16A16_FLOAT:
1010 STORE_SCANLINE( XMHALF4, XMStoreHalf4 )
1012 case DXGI_FORMAT_R16G16B16A16_UNORM:
1013 STORE_SCANLINE( XMUSHORTN4, XMStoreUShortN4 )
1015 case DXGI_FORMAT_R16G16B16A16_UINT:
1016 STORE_SCANLINE( XMUSHORT4, XMStoreUShort4 )
1018 case DXGI_FORMAT_R16G16B16A16_SNORM:
1019 STORE_SCANLINE( XMSHORTN4, XMStoreShortN4 )
1021 case DXGI_FORMAT_R16G16B16A16_SINT:
1022 STORE_SCANLINE( XMSHORT4, XMStoreShort4 )
1024 case DXGI_FORMAT_R32G32_FLOAT:
1025 STORE_SCANLINE( XMFLOAT2, XMStoreFloat2 )
1027 case DXGI_FORMAT_R32G32_UINT:
1028 STORE_SCANLINE( XMUINT2, XMStoreUInt2 )
1030 case DXGI_FORMAT_R32G32_SINT:
1031 STORE_SCANLINE( XMINT2, XMStoreSInt2 )
1033 case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
1034 if ( size >= (sizeof(float)+sizeof(uint32_t)) )
1036 float *dPtr = reinterpret_cast<float*>(pDestination);
1037 for( size_t icount = 0; icount < size; icount += (sizeof(float)+sizeof(uint32_t)) )
1039 if ( sPtr >= ePtr ) break;
1041 XMStoreFloat4( &f, *sPtr++ );
1043 uint8_t* ps8 = reinterpret_cast<uint8_t*>( &dPtr[1] );
1044 ps8[0] = static_cast<uint8_t>( std::min<float>( 255.f, std::max<float>( 0.f, f.y ) ) );
1045 ps8[1] = ps8[2] = ps8[3] = 0;
1051 case DXGI_FORMAT_R10G10B10A2_UNORM:
1052 case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
1053 STORE_SCANLINE( XMUDECN4, XMStoreUDecN4 );
1055 case DXGI_FORMAT_R10G10B10A2_UINT:
1056 STORE_SCANLINE( XMUDEC4, XMStoreUDec4 );
1058 case DXGI_FORMAT_R11G11B10_FLOAT:
1059 STORE_SCANLINE( XMFLOAT3PK, XMStoreFloat3PK );
1061 case DXGI_FORMAT_R8G8B8A8_UNORM:
1062 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
1063 STORE_SCANLINE( XMUBYTEN4, XMStoreUByteN4 )
1065 case DXGI_FORMAT_R8G8B8A8_UINT:
1066 STORE_SCANLINE( XMUBYTE4, XMStoreUByte4 )
1068 case DXGI_FORMAT_R8G8B8A8_SNORM:
1069 STORE_SCANLINE( XMBYTEN4, XMStoreByteN4 )
1071 case DXGI_FORMAT_R8G8B8A8_SINT:
1072 STORE_SCANLINE( XMBYTE4, XMStoreByte4 )
1074 case DXGI_FORMAT_R16G16_FLOAT:
1075 STORE_SCANLINE( XMHALF2, XMStoreHalf2 )
1077 case DXGI_FORMAT_R16G16_UNORM:
1078 STORE_SCANLINE( XMUSHORTN2, XMStoreUShortN2 )
1080 case DXGI_FORMAT_R16G16_UINT:
1081 STORE_SCANLINE( XMUSHORT2, XMStoreUShort2 )
1083 case DXGI_FORMAT_R16G16_SNORM:
1084 STORE_SCANLINE( XMSHORTN2, XMStoreShortN2 )
1086 case DXGI_FORMAT_R16G16_SINT:
1087 STORE_SCANLINE( XMSHORT2, XMStoreShort2 )
1089 case DXGI_FORMAT_D32_FLOAT:
1090 case DXGI_FORMAT_R32_FLOAT:
1091 if ( size >= sizeof(float) )
1093 float * __restrict dPtr = reinterpret_cast<float*>(pDestination);
1094 for( size_t icount = 0; icount < size; icount += sizeof(float) )
1096 if ( sPtr >= ePtr ) break;
1097 XMStoreFloat( dPtr++, *(sPtr++) );
1102 case DXGI_FORMAT_R32_UINT:
1103 if ( size >= sizeof(uint32_t) )
1105 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
1106 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1108 if ( sPtr >= ePtr ) break;
1109 XMVECTOR v = XMConvertVectorFloatToUInt( *(sPtr++), 0 );
1110 XMStoreInt( dPtr++, v );
1115 case DXGI_FORMAT_R32_SINT:
1116 if ( size >= sizeof(uint32_t) )
1118 uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
1119 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1121 if ( sPtr >= ePtr ) break;
1122 XMVECTOR v = XMConvertVectorFloatToInt( *(sPtr++), 0 );
1123 XMStoreInt( dPtr++, v );
1128 case DXGI_FORMAT_D24_UNORM_S8_UINT:
1129 if ( size >= sizeof(uint32_t) )
1131 static const XMVECTORF32 clamp = { 1.f, 255.f, 0.f, 0.f };
1132 XMVECTOR zero = XMVectorZero();
1133 uint32_t *dPtr = reinterpret_cast<uint32_t*>(pDestination);
1134 for( size_t icount = 0; icount < size; icount += sizeof(uint32_t) )
1136 if ( sPtr >= ePtr ) break;
1138 XMStoreFloat4( &f, XMVectorClamp( *sPtr++, zero, clamp ) );
1139 *dPtr++ = (static_cast<uint32_t>( f.x * 16777215.f ) & 0xFFFFFF)
1140 | ((static_cast<uint32_t>( f.y ) & 0xFF) << 24);
1145 case DXGI_FORMAT_R8G8_UNORM:
1146 STORE_SCANLINE( XMUBYTEN2, XMStoreUByteN2 )
1148 case DXGI_FORMAT_R8G8_UINT:
1149 STORE_SCANLINE( XMUBYTE2, XMStoreUByte2 )
1151 case DXGI_FORMAT_R8G8_SNORM:
1152 STORE_SCANLINE( XMBYTEN2, XMStoreByteN2 )
1154 case DXGI_FORMAT_R8G8_SINT:
1155 STORE_SCANLINE( XMBYTE2, XMStoreByte2 )
1157 case DXGI_FORMAT_R16_FLOAT:
1158 if ( size >= sizeof(HALF) )
1160 HALF * __restrict dPtr = reinterpret_cast<HALF*>(pDestination);
1161 for( size_t icount = 0; icount < size; icount += sizeof(HALF) )
1163 if ( sPtr >= ePtr ) break;
1164 float v = XMVectorGetX( *sPtr++ );
1165 *(dPtr++) = XMConvertFloatToHalf(v);
1170 case DXGI_FORMAT_D16_UNORM:
1171 case DXGI_FORMAT_R16_UNORM:
1172 if ( size >= sizeof(int16_t) )
1174 int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1175 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
1177 if ( sPtr >= ePtr ) break;
1178 float v = XMVectorGetX( *sPtr++ );
1179 v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
1180 *(dPtr++) = static_cast<uint16_t>( v*65535.f + 0.5f );
1185 case DXGI_FORMAT_R16_UINT:
1186 if ( size >= sizeof(uint16_t) )
1188 uint16_t * __restrict dPtr = reinterpret_cast<uint16_t*>(pDestination);
1189 for( size_t icount = 0; icount < size; icount += sizeof(uint16_t) )
1191 if ( sPtr >= ePtr ) break;
1192 float v = XMVectorGetX( *sPtr++ );
1193 v = std::max<float>( std::min<float>( v, 65535.f ), 0.f );
1194 *(dPtr++) = static_cast<uint16_t>(v);
1199 case DXGI_FORMAT_R16_SNORM:
1200 if ( size >= sizeof(int16_t) )
1202 int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1203 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
1205 if ( sPtr >= ePtr ) break;
1206 float v = XMVectorGetX( *sPtr++ );
1207 v = std::max<float>( std::min<float>( v, 1.f ), -1.f );
1208 *(dPtr++) = static_cast<uint16_t>( v * 32767.f );
1213 case DXGI_FORMAT_R16_SINT:
1214 if ( size >= sizeof(int16_t) )
1216 int16_t * __restrict dPtr = reinterpret_cast<int16_t*>(pDestination);
1217 for( size_t icount = 0; icount < size; icount += sizeof(int16_t) )
1219 if ( sPtr >= ePtr ) break;
1220 float v = XMVectorGetX( *sPtr++ );
1221 v = std::max<float>( std::min<float>( v, 32767.f ), -32767.f );
1222 *(dPtr++) = static_cast<int16_t>(v);
1227 case DXGI_FORMAT_R8_UNORM:
1228 if ( size >= sizeof(uint8_t) )
1230 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1231 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1233 if ( sPtr >= ePtr ) break;
1234 float v = XMVectorGetX( *sPtr++ );
1235 v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
1236 *(dPtr++) = static_cast<uint8_t>( v * 255.f);
1241 case DXGI_FORMAT_R8_UINT:
1242 if ( size >= sizeof(uint8_t) )
1244 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1245 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1247 if ( sPtr >= ePtr ) break;
1248 float v = XMVectorGetX( *sPtr++ );
1249 v = std::max<float>( std::min<float>( v, 255.f ), 0.f );
1250 *(dPtr++) = static_cast<uint8_t>(v);
1255 case DXGI_FORMAT_R8_SNORM:
1256 if ( size >= sizeof(char) )
1258 char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
1259 for( size_t icount = 0; icount < size; icount += sizeof(char) )
1261 if ( sPtr >= ePtr ) break;
1262 float v = XMVectorGetX( *sPtr++ );
1263 v = std::max<float>( std::min<float>( v, 1.f ), -1.f );
1264 *(dPtr++) = static_cast<char>( v * 127.f );
1269 case DXGI_FORMAT_R8_SINT:
1270 if ( size >= sizeof(char) )
1272 char * __restrict dPtr = reinterpret_cast<char*>(pDestination);
1273 for( size_t icount = 0; icount < size; icount += sizeof(char) )
1275 if ( sPtr >= ePtr ) break;
1276 float v = XMVectorGetX( *sPtr++ );
1277 v = std::max<float>( std::min<float>( v, 127.f ), -127.f );
1278 *(dPtr++) = static_cast<char>( v );
1283 case DXGI_FORMAT_A8_UNORM:
1284 if ( size >= sizeof(uint8_t) )
1286 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1287 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1289 if ( sPtr >= ePtr ) break;
1290 float v = XMVectorGetW( *sPtr++ );
1291 v = std::max<float>( std::min<float>( v, 1.f ), 0.f );
1292 *(dPtr++) = static_cast<uint8_t>( v * 255.f);
1297 case DXGI_FORMAT_R1_UNORM:
1298 if ( size >= sizeof(uint8_t) )
1300 uint8_t * __restrict dPtr = reinterpret_cast<uint8_t*>(pDestination);
1301 for( size_t icount = 0; icount < size; icount += sizeof(uint8_t) )
1304 for( size_t bcount = 0; bcount < 8; ++bcount )
1306 if ( sPtr >= ePtr ) break;
1307 float v = XMVectorGetX( *sPtr++ );
1309 pixels |= 1 << bcount;
1316 case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
1317 STORE_SCANLINE( XMFLOAT3SE, XMStoreFloat3SE )
1319 case DXGI_FORMAT_R8G8_B8G8_UNORM:
1320 if ( size >= sizeof(XMUBYTEN4) )
1322 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1323 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1325 if ( sPtr >= ePtr ) break;
1326 XMVECTOR v0 = *sPtr++;
1327 XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY( *sPtr++ ) : XMVectorZero();
1328 XMVECTOR v = XMVectorSelect( v1, v0, g_XMSelect1110 );
1329 XMStoreUByteN4( dPtr++, v );
1334 case DXGI_FORMAT_G8R8_G8B8_UNORM:
1335 if ( size >= sizeof(XMUBYTEN4) )
1337 static XMVECTORI32 select1101 = {XM_SELECT_1, XM_SELECT_1, XM_SELECT_0, XM_SELECT_1};
1339 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1340 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1342 if ( sPtr >= ePtr ) break;
1343 XMVECTOR v0 = XMVectorSwizzle<1, 0, 3, 2>( *sPtr++ );
1344 XMVECTOR v1 = (sPtr < ePtr) ? XMVectorSplatY( *sPtr++ ) : XMVectorZero();
1345 XMVECTOR v = XMVectorSelect( v1, v0, select1101 );
1346 XMStoreUByteN4( dPtr++, v );
1351 case DXGI_FORMAT_B5G6R5_UNORM:
1352 if ( size >= sizeof(XMU565) )
1354 static XMVECTORF32 s_Scale = { 31.f, 63.f, 31.f, 1.f };
1355 XMU565 * __restrict dPtr = reinterpret_cast<XMU565*>(pDestination);
1356 for( size_t icount = 0; icount < size; icount += sizeof(XMU565) )
1358 if ( sPtr >= ePtr ) break;
1359 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1360 v = XMVectorMultiply( v, s_Scale );
1361 XMStoreU565( dPtr++, v );
1366 case DXGI_FORMAT_B5G5R5A1_UNORM:
1367 if ( size >= sizeof(XMU555) )
1369 static XMVECTORF32 s_Scale = { 31.f, 31.f, 31.f, 1.f };
1370 XMU555 * __restrict dPtr = reinterpret_cast<XMU555*>(pDestination);
1371 for( size_t icount = 0; icount < size; icount += sizeof(XMU555) )
1373 if ( sPtr >= ePtr ) break;
1374 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1375 v = XMVectorMultiply( v, s_Scale );
1376 XMStoreU555( dPtr++, v );
1381 case DXGI_FORMAT_B8G8R8A8_UNORM:
1382 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
1383 if ( size >= sizeof(XMUBYTEN4) )
1385 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1386 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1388 if ( sPtr >= ePtr ) break;
1389 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1390 XMStoreUByteN4( dPtr++, v );
1395 case DXGI_FORMAT_B8G8R8X8_UNORM:
1396 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
1397 if ( size >= sizeof(XMUBYTEN4) )
1399 XMUBYTEN4 * __restrict dPtr = reinterpret_cast<XMUBYTEN4*>(pDestination);
1400 for( size_t icount = 0; icount < size; icount += sizeof(XMUBYTEN4) )
1402 if ( sPtr >= ePtr ) break;
1403 XMVECTOR v = XMVectorPermute<2, 1, 0, 7>( *sPtr++, g_XMIdentityR3 );
1404 XMStoreUByteN4( dPtr++, v );
1409 #ifdef DXGI_1_2_FORMATS
1410 case DXGI_FORMAT_B4G4R4A4_UNORM:
1411 if ( size >= sizeof(XMUNIBBLE4) )
1413 static XMVECTORF32 s_Scale = { 15.f, 15.f, 15.f, 15.f };
1414 XMUNIBBLE4 * __restrict dPtr = reinterpret_cast<XMUNIBBLE4*>(pDestination);
1415 for( size_t icount = 0; icount < size; icount += sizeof(XMUNIBBLE4) )
1417 if ( sPtr >= ePtr ) break;
1418 XMVECTOR v = XMVectorSwizzle<2, 1, 0, 3>( *sPtr++ );
1419 v = XMVectorMultiply( v, s_Scale );
1420 XMStoreUNibble4( dPtr++, v );
1425 // We don't support the video formats ( see IsVideo function )
1426 #endif // DXGI_1_2_FORMATS
1434 //-------------------------------------------------------------------------------------
1435 // Convert DXGI image to/from GUID_WICPixelFormat128bppRGBAFloat (no range conversions)
1436 //-------------------------------------------------------------------------------------
1437 HRESULT _ConvertToR32G32B32A32( const Image& srcImage, ScratchImage& image )
1439 if ( !srcImage.pixels )
1442 HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
1446 const Image *img = image.GetImage( 0, 0, 0 );
1453 uint8_t* pDest = img->pixels;
1460 const uint8_t *pSrc = srcImage.pixels;
1461 for( size_t h = 0; h < srcImage.height; ++h )
1463 if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
1469 pSrc += srcImage.rowPitch;
1470 pDest += img->rowPitch;
1476 HRESULT _ConvertFromR32G32B32A32( _In_ const Image& srcImage, _In_ const Image& destImage )
1478 assert( srcImage.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1480 if ( !srcImage.pixels || !destImage.pixels )
1483 if ( srcImage.width != destImage.width || srcImage.height != destImage.height )
1486 const uint8_t *pSrc = srcImage.pixels;
1487 uint8_t* pDest = destImage.pixels;
1489 for( size_t h = 0; h < srcImage.height; ++h )
1491 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
1494 pSrc += srcImage.rowPitch;
1495 pDest += destImage.rowPitch;
1501 HRESULT _ConvertFromR32G32B32A32( const Image& srcImage, DXGI_FORMAT format, ScratchImage& image )
1503 if ( !srcImage.pixels )
1506 HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
1510 const Image *img = image.GetImage( 0, 0, 0 );
1517 hr = _ConvertFromR32G32B32A32( srcImage, *img );
1527 HRESULT _ConvertFromR32G32B32A32( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DXGI_FORMAT format, ScratchImage& result )
1534 assert( metadata.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1536 TexMetadata mdata2 = metadata;
1537 mdata2.format = format;
1538 HRESULT hr = result.Initialize( mdata2 );
1542 if ( nimages != result.GetImageCount() )
1548 const Image* dest = result.GetImages();
1555 for( size_t index=0; index < nimages; ++index )
1557 const Image& src = srcImages[ index ];
1558 const Image& dst = dest[ index ];
1560 assert( src.format == DXGI_FORMAT_R32G32B32A32_FLOAT );
1561 assert( dst.format == format );
1563 if ( src.width != dst.width || src.height != dst.height )
1569 const uint8_t* pSrc = src.pixels;
1570 uint8_t* pDest = dst.pixels;
1571 if ( !pSrc || !pDest )
1577 for( size_t h=0; h < src.height; ++h )
1579 if ( !_StoreScanline( pDest, dst.rowPitch, format, reinterpret_cast<const XMVECTOR*>(pSrc), src.width ) )
1585 pSrc += src.rowPitch;
1586 pDest += dst.rowPitch;
1594 //-------------------------------------------------------------------------------------
1596 //-------------------------------------------------------------------------------------
1597 static const uint32_t g_fEncodeGamma22[] =
1599 0x00000000, 0x3bd56bd3, 0x3c486344, 0x3c90da15, 0x3cbc2677, 0x3ce67704, 0x3d080183, 0x3d1c7728,
1600 0x3d30a8fb, 0x3d44a03c, 0x3d586400, 0x3d6bf9e7, 0x3d7f6679, 0x3d8956bd, 0x3d92e906, 0x3d9c6b70,
1601 0x3da5df22, 0x3daf451b, 0x3db89e3e, 0x3dc1eb50, 0x3dcb2d04, 0x3dd463f7, 0x3ddd90b9, 0x3de6b3ca,
1602 0x3defcda0, 0x3df8dea6, 0x3e00f3a0, 0x3e0573e3, 0x3e09f046, 0x3e0e68f0, 0x3e12de06, 0x3e174fa6,
1603 0x3e1bbdf2, 0x3e202906, 0x3e2490fd, 0x3e28f5f1, 0x3e2d57fb, 0x3e31b72f, 0x3e3613a4, 0x3e3a6d6e,
1604 0x3e3ec4a0, 0x3e43194d, 0x3e476b84, 0x3e4bbb57, 0x3e5008d7, 0x3e54540f, 0x3e589d0f, 0x3e5ce3e5,
1605 0x3e61289d, 0x3e656b44, 0x3e69abe5, 0x3e6dea8d, 0x3e722745, 0x3e766217, 0x3e7a9b0e, 0x3e7ed235,
1606 0x3e8183c9, 0x3e839d98, 0x3e85b68c, 0x3e87cea8, 0x3e89e5f2, 0x3e8bfc6b, 0x3e8e1219, 0x3e9026ff,
1607 0x3e923b20, 0x3e944e7f, 0x3e966120, 0x3e987307, 0x3e9a8436, 0x3e9c94af, 0x3e9ea476, 0x3ea0b38e,
1608 0x3ea2c1fb, 0x3ea4cfbb, 0x3ea6dcd5, 0x3ea8e94a, 0x3eaaf51c, 0x3ead004e, 0x3eaf0ae2, 0x3eb114d9,
1609 0x3eb31e37, 0x3eb526fe, 0x3eb72f2f, 0x3eb936cd, 0x3ebb3dd8, 0x3ebd4454, 0x3ebf4a43, 0x3ec14fa5,
1610 0x3ec3547e, 0x3ec558cd, 0x3ec75c95, 0x3ec95fd8, 0x3ecb6297, 0x3ecd64d4, 0x3ecf6690, 0x3ed167ce,
1611 0x3ed3688e, 0x3ed568d1, 0x3ed76899, 0x3ed967e9, 0x3edb66bf, 0x3edd651f, 0x3edf630a, 0x3ee16080,
1612 0x3ee35d84, 0x3ee55a16, 0x3ee75636, 0x3ee951e8, 0x3eeb4d2a, 0x3eed4800, 0x3eef4269, 0x3ef13c68,
1613 0x3ef335fc, 0x3ef52f26, 0x3ef727ea, 0x3ef92046, 0x3efb183c, 0x3efd0fcd, 0x3eff06fa, 0x3f007ee2,
1614 0x3f017a16, 0x3f027519, 0x3f036fec, 0x3f046a8f, 0x3f056502, 0x3f065f47, 0x3f07595d, 0x3f085344,
1615 0x3f094cfe, 0x3f0a468b, 0x3f0b3feb, 0x3f0c391e, 0x3f0d3224, 0x3f0e2aff, 0x3f0f23af, 0x3f101c32,
1616 0x3f11148c, 0x3f120cba, 0x3f1304bf, 0x3f13fc9a, 0x3f14f44b, 0x3f15ebd3, 0x3f16e333, 0x3f17da6b,
1617 0x3f18d17a, 0x3f19c860, 0x3f1abf1f, 0x3f1bb5b7, 0x3f1cac28, 0x3f1da272, 0x3f1e9895, 0x3f1f8e92,
1618 0x3f20846a, 0x3f217a1c, 0x3f226fa8, 0x3f23650f, 0x3f245a52, 0x3f254f70, 0x3f264469, 0x3f27393f,
1619 0x3f282df1, 0x3f29227f, 0x3f2a16ea, 0x3f2b0b31, 0x3f2bff56, 0x3f2cf358, 0x3f2de738, 0x3f2edaf6,
1620 0x3f2fce91, 0x3f30c20b, 0x3f31b564, 0x3f32a89b, 0x3f339bb1, 0x3f348ea6, 0x3f35817a, 0x3f36742f,
1621 0x3f3766c3, 0x3f385936, 0x3f394b8a, 0x3f3a3dbe, 0x3f3b2fd3, 0x3f3c21c8, 0x3f3d139e, 0x3f3e0556,
1622 0x3f3ef6ee, 0x3f3fe868, 0x3f40d9c4, 0x3f41cb01, 0x3f42bc20, 0x3f43ad22, 0x3f449e06, 0x3f458ecc,
1623 0x3f467f75, 0x3f477001, 0x3f486071, 0x3f4950c2, 0x3f4a40f8, 0x3f4b3111, 0x3f4c210d, 0x3f4d10ed,
1624 0x3f4e00b2, 0x3f4ef05a, 0x3f4fdfe7, 0x3f50cf58, 0x3f51beae, 0x3f52ade8, 0x3f539d07, 0x3f548c0c,
1625 0x3f557af5, 0x3f5669c4, 0x3f575878, 0x3f584711, 0x3f593590, 0x3f5a23f6, 0x3f5b1241, 0x3f5c0072,
1626 0x3f5cee89, 0x3f5ddc87, 0x3f5eca6b, 0x3f5fb835, 0x3f60a5e7, 0x3f619380, 0x3f6280ff, 0x3f636e65,
1627 0x3f645bb3, 0x3f6548e8, 0x3f663604, 0x3f672309, 0x3f680ff4, 0x3f68fcc8, 0x3f69e983, 0x3f6ad627,
1628 0x3f6bc2b3, 0x3f6caf27, 0x3f6d9b83, 0x3f6e87c8, 0x3f6f73f5, 0x3f70600c, 0x3f714c0b, 0x3f7237f4,
1629 0x3f7323c4, 0x3f740f7f, 0x3f74fb22, 0x3f75e6af, 0x3f76d225, 0x3f77bd85, 0x3f78a8ce, 0x3f799401,
1630 0x3f7a7f1e, 0x3f7b6a25, 0x3f7c5516, 0x3f7d3ff1, 0x3f7e2ab6, 0x3f7f1566, 0x3f800000, 0x3f800000
1633 #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
1634 static inline XMVECTOR _TableEncodeGamma22( FXMVECTOR v )
1637 XMStoreFloat4( (XMFLOAT4*)f, v );
1639 for( size_t i=0; i < 4; ++i )
1641 float f2 = sqrtf(f[i]) * 254.0f;
1643 uint32_t i2 = static_cast<uint32_t>(f2);
1644 i2 = std::min<uint32_t>( i2, _countof( g_fEncodeGamma22 )-2 );
1646 float fS = f2 - (float) i2;
1647 float fA = ((float *) g_fEncodeGamma22)[i2];
1648 float fB = ((float *) g_fEncodeGamma22)[i2 + 1];
1650 f[i] = fA + fS * (fB - fA);
1653 return XMLoadFloat4( (XMFLOAT4*)f );
1657 //-------------------------------------------------------------------------------------
1659 //-------------------------------------------------------------------------------------
1660 static const uint32_t g_fDecodeGamma22[] =
1662 0x00000000, 0x3b144eb0, 0x3b9ef3b0, 0x3bf84b42, 0x3c2a5c46, 0x3c59c180, 0x3c850eb5, 0x3c9da52a,
1663 0x3cb6967a, 0x3ccfd852, 0x3ce9628b, 0x3d01974b, 0x3d0e9b82, 0x3d1bbba3, 0x3d28f5bc, 0x3d364822,
1664 0x3d43b159, 0x3d51301d, 0x3d5ec344, 0x3d6c69c9, 0x3d7a22c4, 0x3d83f6ad, 0x3d8ae465, 0x3d91da35,
1665 0x3d98d7c7, 0x3d9fdcd2, 0x3da6e914, 0x3dadfc47, 0x3db51635, 0x3dbc36a3, 0x3dc35d62, 0x3dca8a3a,
1666 0x3dd1bd02, 0x3dd8f591, 0x3de033bb, 0x3de7775d, 0x3deec050, 0x3df60e74, 0x3dfd61a6, 0x3e025ce5,
1667 0x3e060b61, 0x3e09bc38, 0x3e0d6f5f, 0x3e1124c8, 0x3e14dc68, 0x3e189630, 0x3e1c521a, 0x3e201016,
1668 0x3e23d01d, 0x3e279225, 0x3e2b5624, 0x3e2f1c10, 0x3e32e3e4, 0x3e36ad94, 0x3e3a7918, 0x3e3e4668,
1669 0x3e42157f, 0x3e45e654, 0x3e49b8e0, 0x3e4d8d1d, 0x3e516304, 0x3e553a8d, 0x3e5913b4, 0x3e5cee70,
1670 0x3e60cabf, 0x3e64a89b, 0x3e6887fb, 0x3e6c68db, 0x3e704b3a, 0x3e742f0e, 0x3e781454, 0x3e7bfb04,
1671 0x3e7fe321, 0x3e81e650, 0x3e83dbc0, 0x3e85d1dc, 0x3e87c8a3, 0x3e89c015, 0x3e8bb830, 0x3e8db0ee,
1672 0x3e8faa51, 0x3e91a454, 0x3e939ef9, 0x3e959a3b, 0x3e97961b, 0x3e999295, 0x3e9b8fa7, 0x3e9d8d52,
1673 0x3e9f8b93, 0x3ea18a6a, 0x3ea389d2, 0x3ea589cb, 0x3ea78a56, 0x3ea98b6e, 0x3eab8d15, 0x3ead8f47,
1674 0x3eaf9204, 0x3eb1954a, 0x3eb39917, 0x3eb59d6c, 0x3eb7a246, 0x3eb9a7a5, 0x3ebbad88, 0x3ebdb3ec,
1675 0x3ebfbad3, 0x3ec1c237, 0x3ec3ca1a, 0x3ec5d27c, 0x3ec7db58, 0x3ec9e4b4, 0x3ecbee85, 0x3ecdf8d3,
1676 0x3ed0039a, 0x3ed20ed8, 0x3ed41a8a, 0x3ed626b5, 0x3ed83351, 0x3eda4065, 0x3edc4de9, 0x3ede5be0,
1677 0x3ee06a4a, 0x3ee27923, 0x3ee4886a, 0x3ee69821, 0x3ee8a845, 0x3eeab8d8, 0x3eecc9d6, 0x3eeedb3f,
1678 0x3ef0ed13, 0x3ef2ff53, 0x3ef511fb, 0x3ef7250a, 0x3ef93883, 0x3efb4c61, 0x3efd60a7, 0x3eff7553,
1679 0x3f00c531, 0x3f01cfeb, 0x3f02dad9, 0x3f03e5f5, 0x3f04f145, 0x3f05fcc4, 0x3f070875, 0x3f081456,
1680 0x3f092067, 0x3f0a2ca8, 0x3f0b3917, 0x3f0c45b7, 0x3f0d5284, 0x3f0e5f7f, 0x3f0f6caa, 0x3f107a03,
1681 0x3f118789, 0x3f12953b, 0x3f13a31d, 0x3f14b12b, 0x3f15bf64, 0x3f16cdca, 0x3f17dc5e, 0x3f18eb1b,
1682 0x3f19fa05, 0x3f1b091b, 0x3f1c185c, 0x3f1d27c7, 0x3f1e375c, 0x3f1f471d, 0x3f205707, 0x3f21671b,
1683 0x3f227759, 0x3f2387c2, 0x3f249852, 0x3f25a90c, 0x3f26b9ef, 0x3f27cafb, 0x3f28dc30, 0x3f29ed8b,
1684 0x3f2aff11, 0x3f2c10bd, 0x3f2d2290, 0x3f2e348b, 0x3f2f46ad, 0x3f3058f7, 0x3f316b66, 0x3f327dfd,
1685 0x3f3390ba, 0x3f34a39d, 0x3f35b6a7, 0x3f36c9d6, 0x3f37dd2b, 0x3f38f0a5, 0x3f3a0443, 0x3f3b1808,
1686 0x3f3c2bf2, 0x3f3d4000, 0x3f3e5434, 0x3f3f688c, 0x3f407d07, 0x3f4191a8, 0x3f42a66c, 0x3f43bb54,
1687 0x3f44d05f, 0x3f45e58e, 0x3f46fadf, 0x3f481054, 0x3f4925ed, 0x3f4a3ba8, 0x3f4b5186, 0x3f4c6789,
1688 0x3f4d7daa, 0x3f4e93f0, 0x3f4faa57, 0x3f50c0e0, 0x3f51d78b, 0x3f52ee58, 0x3f540545, 0x3f551c55,
1689 0x3f563386, 0x3f574ad7, 0x3f58624b, 0x3f5979de, 0x3f5a9191, 0x3f5ba965, 0x3f5cc15b, 0x3f5dd971,
1690 0x3f5ef1a6, 0x3f6009fc, 0x3f612272, 0x3f623b08, 0x3f6353bc, 0x3f646c90, 0x3f658586, 0x3f669e98,
1691 0x3f67b7cb, 0x3f68d11b, 0x3f69ea8d, 0x3f6b041b, 0x3f6c1dc9, 0x3f6d3795, 0x3f6e5180, 0x3f6f6b8b,
1692 0x3f7085b2, 0x3f719ff7, 0x3f72ba5b, 0x3f73d4dc, 0x3f74ef7c, 0x3f760a38, 0x3f772512, 0x3f78400b,
1693 0x3f795b20, 0x3f7a7651, 0x3f7b91a2, 0x3f7cad0e, 0x3f7dc896, 0x3f7ee43c, 0x3f800000, 0x3f800000
1697 #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
1698 static inline XMVECTOR _TableDecodeGamma22( FXMVECTOR v )
1701 XMStoreFloat4( (XMFLOAT4*)f, v );
1703 for( size_t i=0; i < 4; ++i )
1705 float f2 = f[i] * f[i] * 254.0f;
1706 uint32_t i2 = static_cast<uint32_t>(f2);
1707 i2 = std::min<uint32_t>( i2, _countof(g_fDecodeGamma22)-2 );
1709 float fS = f2 - (float) i2;
1710 float fA = ((float *) g_fDecodeGamma22)[i2];
1711 float fB = ((float *) g_fDecodeGamma22)[i2 + 1];
1713 f[i] = fA + fS * (fB - fA);
1716 return XMLoadFloat4( (XMFLOAT4*)f );
1720 //-------------------------------------------------------------------------------------
1721 // Convert scanline based on source/target formats
1722 //-------------------------------------------------------------------------------------
1730 static const ConvertData g_ConvertTable[] = {
1731 { DXGI_FORMAT_R32G32B32A32_FLOAT, 32, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1732 { DXGI_FORMAT_R32G32B32A32_UINT, 32, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1733 { DXGI_FORMAT_R32G32B32A32_SINT, 32, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1734 { DXGI_FORMAT_R32G32B32_FLOAT, 32, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B },
1735 { DXGI_FORMAT_R32G32B32_UINT, 32, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B },
1736 { DXGI_FORMAT_R32G32B32_SINT, 32, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B },
1737 { DXGI_FORMAT_R16G16B16A16_FLOAT, 16, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1738 { DXGI_FORMAT_R16G16B16A16_UNORM, 16, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1739 { DXGI_FORMAT_R16G16B16A16_UINT, 16, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1740 { DXGI_FORMAT_R16G16B16A16_SNORM, 16, CONVF_SNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1741 { DXGI_FORMAT_R16G16B16A16_SINT, 16, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1742 { DXGI_FORMAT_R32G32_FLOAT, 32, CONVF_FLOAT | CONVF_R | CONVF_G },
1743 { DXGI_FORMAT_R32G32_UINT, 32, CONVF_UINT | CONVF_R | CONVF_G },
1744 { DXGI_FORMAT_R32G32_SINT, 32, CONVF_SINT | CONVF_R | CONVF_G },
1745 { DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, CONVF_FLOAT | CONVF_DEPTH | CONVF_STENCIL },
1746 { DXGI_FORMAT_R10G10B10A2_UNORM, 10, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1747 { DXGI_FORMAT_R10G10B10A2_UINT, 10, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1748 { DXGI_FORMAT_R11G11B10_FLOAT, 10, CONVF_FLOAT | CONVF_R | CONVF_G | CONVF_B },
1749 { DXGI_FORMAT_R8G8B8A8_UNORM, 8, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1750 { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1751 { DXGI_FORMAT_R8G8B8A8_UINT, 8, CONVF_UINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1752 { DXGI_FORMAT_R8G8B8A8_SNORM, 8, CONVF_SNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1753 { DXGI_FORMAT_R8G8B8A8_SINT, 8, CONVF_SINT | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1754 { DXGI_FORMAT_R16G16_FLOAT, 16, CONVF_FLOAT | CONVF_R | CONVF_G },
1755 { DXGI_FORMAT_R16G16_UNORM, 16, CONVF_UNORM | CONVF_R | CONVF_G },
1756 { DXGI_FORMAT_R16G16_UINT, 16, CONVF_UINT | CONVF_R | CONVF_G },
1757 { DXGI_FORMAT_R16G16_SNORM, 16, CONVF_SNORM | CONVF_R | CONVF_G },
1758 { DXGI_FORMAT_R16G16_SINT, 16, CONVF_SINT | CONVF_R | CONVF_G },
1759 { DXGI_FORMAT_D32_FLOAT, 32, CONVF_FLOAT | CONVF_DEPTH },
1760 { DXGI_FORMAT_R32_FLOAT, 32, CONVF_FLOAT | CONVF_R },
1761 { DXGI_FORMAT_R32_UINT, 32, CONVF_UINT | CONVF_R },
1762 { DXGI_FORMAT_R32_SINT, 32, CONVF_SINT | CONVF_R },
1763 { DXGI_FORMAT_D24_UNORM_S8_UINT, 32, CONVF_UNORM | CONVF_DEPTH | CONVF_STENCIL },
1764 { DXGI_FORMAT_R8G8_UNORM, 8, CONVF_UNORM | CONVF_R | CONVF_G },
1765 { DXGI_FORMAT_R8G8_UINT, 8, CONVF_UINT | CONVF_R | CONVF_G },
1766 { DXGI_FORMAT_R8G8_SNORM, 8, CONVF_SNORM | CONVF_R | CONVF_G },
1767 { DXGI_FORMAT_R8G8_SINT, 8, CONVF_SINT | CONVF_R | CONVF_G },
1768 { DXGI_FORMAT_R16_FLOAT, 16, CONVF_FLOAT | CONVF_R },
1769 { DXGI_FORMAT_D16_UNORM, 16, CONVF_UNORM | CONVF_DEPTH },
1770 { DXGI_FORMAT_R16_UNORM, 16, CONVF_UNORM | CONVF_R },
1771 { DXGI_FORMAT_R16_UINT, 16, CONVF_UINT | CONVF_R },
1772 { DXGI_FORMAT_R16_SNORM, 16, CONVF_SNORM | CONVF_R },
1773 { DXGI_FORMAT_R16_SINT, 16, CONVF_SINT | CONVF_R },
1774 { DXGI_FORMAT_R8_UNORM, 8, CONVF_UNORM | CONVF_R },
1775 { DXGI_FORMAT_R8_UINT, 8, CONVF_UINT | CONVF_R },
1776 { DXGI_FORMAT_R8_SNORM, 8, CONVF_SNORM | CONVF_R },
1777 { DXGI_FORMAT_R8_SINT, 8, CONVF_SINT | CONVF_R },
1778 { DXGI_FORMAT_A8_UNORM, 8, CONVF_UNORM | CONVF_A },
1779 { DXGI_FORMAT_R1_UNORM, 1, CONVF_UNORM | CONVF_R },
1780 { DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, CONVF_SHAREDEXP | CONVF_R | CONVF_G | CONVF_B },
1781 { DXGI_FORMAT_R8G8_B8G8_UNORM, 8, CONVF_UNORM | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B },
1782 { DXGI_FORMAT_G8R8_G8B8_UNORM, 8, CONVF_UNORM | CONVF_PACKED | CONVF_R | CONVF_G | CONVF_B },
1783 { DXGI_FORMAT_BC1_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1784 { DXGI_FORMAT_BC1_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1785 { DXGI_FORMAT_BC2_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1786 { DXGI_FORMAT_BC2_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1787 { DXGI_FORMAT_BC3_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1788 { DXGI_FORMAT_BC3_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1789 { DXGI_FORMAT_BC4_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R },
1790 { DXGI_FORMAT_BC4_SNORM, 8, CONVF_SNORM | CONVF_BC | CONVF_R },
1791 { DXGI_FORMAT_BC5_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G },
1792 { DXGI_FORMAT_BC5_SNORM, 8, CONVF_SNORM | CONVF_BC | CONVF_R | CONVF_G },
1793 { DXGI_FORMAT_B5G6R5_UNORM, 5, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B },
1794 { DXGI_FORMAT_B5G5R5A1_UNORM, 5, CONVF_UNORM | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1795 { DXGI_FORMAT_B8G8R8A8_UNORM, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1796 { DXGI_FORMAT_B8G8R8X8_UNORM, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B },
1797 { DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, 10, CONVF_UNORM | CONVF_X2 | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1798 { DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1799 { DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B },
1800 { DXGI_FORMAT_BC6H_UF16, 16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1801 { DXGI_FORMAT_BC6H_SF16, 16, CONVF_FLOAT | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1802 { DXGI_FORMAT_BC7_UNORM, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1803 { DXGI_FORMAT_BC7_UNORM_SRGB, 8, CONVF_UNORM | CONVF_BC | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1804 #ifdef DXGI_1_2_FORMATS
1805 { DXGI_FORMAT_B4G4R4A4_UNORM, 4, CONVF_UNORM | CONVF_BGR | CONVF_R | CONVF_G | CONVF_B | CONVF_A },
1809 #pragma prefast( suppress : 25004, "Signature must match bsearch_s" );
1810 static int __cdecl _ConvertCompare( void *context, const void* ptr1, const void *ptr2 )
1812 UNREFERENCED_PARAMETER(context);
1813 const ConvertData *p1 = reinterpret_cast<const ConvertData*>(ptr1);
1814 const ConvertData *p2 = reinterpret_cast<const ConvertData*>(ptr2);
1815 if ( p1->format == p2->format ) return 0;
1816 else return (p1->format < p2->format ) ? -1 : 1;
1819 DWORD _GetConvertFlags( DXGI_FORMAT format )
1822 // Ensure conversion table is in ascending order
1823 assert( _countof(g_ConvertTable) > 0 );
1824 DXGI_FORMAT lastvalue = g_ConvertTable[0].format;
1825 for( size_t index=1; index < _countof(g_ConvertTable); ++index )
1827 assert( g_ConvertTable[index].format > lastvalue );
1828 lastvalue = g_ConvertTable[index].format;
1832 ConvertData key = { format, 0 };
1833 const ConvertData* in = (const ConvertData*) bsearch_s( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1834 _ConvertCompare, 0 );
1835 return (in) ? in->flags : 0;
1838 void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, DXGI_FORMAT inFormat, DWORD flags )
1840 assert( pBuffer && count > 0 && (((uintptr_t)pBuffer & 0xF) == 0) );
1841 assert( IsValid(outFormat) && !IsVideo(outFormat) && !IsTypeless(outFormat) );
1842 assert( IsValid(inFormat) && !IsVideo(inFormat) && !IsTypeless(inFormat) );
1848 // Ensure conversion table is in ascending order
1849 assert( _countof(g_ConvertTable) > 0 );
1850 DXGI_FORMAT lastvalue = g_ConvertTable[0].format;
1851 for( size_t index=1; index < _countof(g_ConvertTable); ++index )
1853 assert( g_ConvertTable[index].format > lastvalue );
1854 lastvalue = g_ConvertTable[index].format;
1858 // Determine conversion details about source and dest formats
1859 ConvertData key = { inFormat, 0 };
1860 const ConvertData* in = (const ConvertData*) bsearch_s( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1861 _ConvertCompare, 0 );
1862 key.format = outFormat;
1863 const ConvertData* out = (const ConvertData*) bsearch_s( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1864 _ConvertCompare, 0 );
1871 assert( _GetConvertFlags( inFormat ) == in->flags );
1872 assert( _GetConvertFlags( outFormat ) == out->flags );
1874 // Handle SRGB filtering modes
1875 if ( IsSRGB( inFormat ) )
1876 flags |= TEX_FILTER_SRGB_IN;
1878 if ( IsSRGB( outFormat ) )
1879 flags |= TEX_FILTER_SRGB_OUT;
1881 if ( in->flags & CONVF_SNORM )
1882 flags &= ~TEX_FILTER_SRGB_IN;
1884 if ( out->flags & CONVF_SNORM )
1885 flags &= ~TEX_FILTER_SRGB_OUT;
1887 if ( (flags & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
1889 flags &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
1892 // sRGB input processing (sRGB -> RGB)
1893 if ( flags & TEX_FILTER_SRGB_IN )
1895 if ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) )
1897 XMVECTOR* ptr = pBuffer;
1898 for( size_t i=0; i < count; ++i )
1900 // rgb = rgb^(2.2); a=a
1902 XMVECTOR v1 = _TableDecodeGamma22( v );
1903 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
1908 // Handle conversion special cases
1909 DWORD diffFlags = in->flags ^ out->flags;
1910 if ( diffFlags != 0)
1912 if ( out->flags & CONVF_UNORM )
1914 if ( in->flags & CONVF_SNORM )
1917 XMVECTOR* ptr = pBuffer;
1918 for( size_t i=0; i < count; ++i )
1921 *ptr++ = XMVectorMultiplyAdd( v, g_XMOneHalf, g_XMOneHalf );
1924 else if ( in->flags & CONVF_FLOAT )
1927 XMVECTOR* ptr = pBuffer;
1928 for( size_t i=0; i < count; ++i )
1931 *ptr++ = XMVectorSaturate( v );
1935 else if ( out->flags & CONVF_SNORM )
1937 if ( in->flags & CONVF_UNORM )
1940 static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
1941 XMVECTOR* ptr = pBuffer;
1942 for( size_t i=0; i < count; ++i )
1945 *ptr++ = XMVectorMultiplyAdd( v, two, g_XMNegativeOne );
1948 else if ( in->flags & CONVF_FLOAT )
1951 XMVECTOR* ptr = pBuffer;
1952 for( size_t i=0; i < count; ++i )
1955 *ptr++ = XMVectorClamp( v, g_XMNegativeOne, g_XMOne );
1960 // !CONVF_A -> CONVF_A is handled because LoadScanline ensures alpha defaults to 1.0 for no-alpha formats
1962 // CONVF_PACKED cases are handled because LoadScanline/StoreScanline handles packing/unpacking
1964 if ( ((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A) )
1966 // !CONVF_A -> A format
1967 XMVECTOR* ptr = pBuffer;
1968 for( size_t i=0; i < count; ++i )
1971 *ptr++ = XMVectorSplatX( v );
1974 else if ( ((in->flags & CONVF_RGBA_MASK) == CONVF_A) && !(out->flags & CONVF_A) )
1976 // A format -> !CONVF_A
1977 XMVECTOR* ptr = pBuffer;
1978 for( size_t i=0; i < count; ++i )
1981 *ptr++ = XMVectorSplatW( v );
1984 else if ( ((in->flags & CONVF_RGB_MASK) == CONVF_R) && ((out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B)) )
1986 // R format -> RGB format
1987 XMVECTOR* ptr = pBuffer;
1988 for( size_t i=0; i < count; ++i )
1991 XMVECTOR v1 = XMVectorSplatX( v );
1992 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
1997 // sRGB output processing (RGB -> sRGB)
1998 if ( flags & TEX_FILTER_SRGB_OUT )
2000 if ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) )
2002 XMVECTOR* ptr = pBuffer;
2003 for( size_t i=0; i < count; ++i )
2005 // rgb = rgb^(1/2.2); a=a
2007 XMVECTOR v1 = _TableEncodeGamma22( v );
2008 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
2015 //-------------------------------------------------------------------------------------
2016 // Convert the source image using WIC
2017 //-------------------------------------------------------------------------------------
2018 static HRESULT _ConvertUsingWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
2019 _In_ const WICPixelFormatGUID& targetGUID,
2020 _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
2022 assert( srcImage.width == destImage.width );
2023 assert( srcImage.height == destImage.height );
2025 IWICImagingFactory* pWIC = _GetWIC();
2027 return E_NOINTERFACE;
2029 ScopedObject<IWICFormatConverter> FC;
2030 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2034 // Need to implement usage of TEX_FILTER_SRGB_IN/TEX_FILTER_SRGB_OUT
2036 BOOL canConvert = FALSE;
2037 hr = FC->CanConvert( pfGUID, targetGUID, &canConvert );
2038 if ( FAILED(hr) || !canConvert )
2040 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2041 return E_UNEXPECTED;
2044 ScopedObject<IWICBitmap> source;
2045 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
2046 static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
2047 srcImage.pixels, &source );
2051 hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2055 hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
2063 //-------------------------------------------------------------------------------------
2064 // Convert the source using WIC and then convert to DXGI format from there
2065 //-------------------------------------------------------------------------------------
2066 static HRESULT _ConvertFromWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
2067 _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
2069 assert( srcImage.width == destImage.width );
2070 assert( srcImage.height == destImage.height );
2072 IWICImagingFactory* pWIC = _GetWIC();
2074 return E_NOINTERFACE;
2076 ScopedObject<IWICFormatConverter> FC;
2077 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2081 BOOL canConvert = FALSE;
2082 hr = FC->CanConvert( pfGUID, GUID_WICPixelFormat128bppRGBAFloat, &canConvert );
2083 if ( FAILED(hr) || !canConvert )
2085 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2086 return E_UNEXPECTED;
2090 hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2094 const Image *timg = temp.GetImage( 0, 0, 0 );
2098 ScopedObject<IWICBitmap> source;
2099 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
2100 static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
2101 srcImage.pixels, &source );
2105 hr = FC->Initialize( source.Get(), GUID_WICPixelFormat128bppRGBAFloat, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2109 hr = FC->CopyPixels( 0, static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ), timg->pixels );
2113 // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format to final image
2114 uint8_t *pSrc = timg->pixels;
2115 uint8_t *pDest = destImage.pixels;
2116 if ( !pSrc || !pDest )
2119 for( size_t h = 0; h < srcImage.height; ++h )
2121 _ConvertScanline( reinterpret_cast<XMVECTOR*>(pSrc), srcImage.width, destImage.format, DXGI_FORMAT_R32G32B32A32_FLOAT, filter );
2123 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
2126 pSrc += timg->rowPitch;
2127 pDest += destImage.rowPitch;
2134 //-------------------------------------------------------------------------------------
2135 // Convert the source from DXGI format then use WIC to convert to final format
2136 //-------------------------------------------------------------------------------------
2137 static HRESULT _ConvertToWIC( _In_ const Image& srcImage,
2138 _In_ const WICPixelFormatGUID& targetGUID, _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
2140 assert( srcImage.width == destImage.width );
2141 assert( srcImage.height == destImage.height );
2143 IWICImagingFactory* pWIC = _GetWIC();
2145 return E_NOINTERFACE;
2147 ScopedObject<IWICFormatConverter> FC;
2148 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2152 BOOL canConvert = FALSE;
2153 hr = FC->CanConvert( GUID_WICPixelFormat128bppRGBAFloat, targetGUID, &canConvert );
2154 if ( FAILED(hr) || !canConvert )
2156 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2157 return E_UNEXPECTED;
2161 hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2165 const Image *timg = temp.GetImage( 0, 0, 0 );
2169 const uint8_t *pSrc = srcImage.pixels;
2173 uint8_t *pDest = timg->pixels;
2177 for( size_t h = 0; h < srcImage.height; ++h )
2179 if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2182 _ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
2184 pSrc += srcImage.rowPitch;
2185 pDest += timg->rowPitch;
2188 // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format
2189 ScopedObject<IWICBitmap> source;
2190 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( timg->width ), static_cast<UINT>( timg->height ), GUID_WICPixelFormat128bppRGBAFloat,
2191 static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ),
2192 timg->pixels, &source );
2196 hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2200 hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
2208 //-------------------------------------------------------------------------------------
2209 // Convert the source image (not using WIC)
2210 //-------------------------------------------------------------------------------------
2211 static HRESULT _Convert( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
2213 assert( srcImage.width == destImage.width );
2214 assert( srcImage.height == destImage.height );
2216 ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
2218 return E_OUTOFMEMORY;
2220 const uint8_t *pSrc = srcImage.pixels;
2221 uint8_t *pDest = destImage.pixels;
2222 if ( !pSrc || !pDest )
2225 for( size_t h = 0; h < srcImage.height; ++h )
2227 if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2230 _ConvertScanline( scanline.get(), srcImage.width, destImage.format, srcImage.format, filter );
2232 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
2235 pSrc += srcImage.rowPitch;
2236 pDest += destImage.rowPitch;
2243 //=====================================================================================
2245 //=====================================================================================
2247 //-------------------------------------------------------------------------------------
2249 //-------------------------------------------------------------------------------------
2250 HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& image )
2252 if ( (srcImage.format == format) || !IsValid( format ) )
2253 return E_INVALIDARG;
2255 if ( !srcImage.pixels )
2258 if ( IsCompressed(srcImage.format) || IsCompressed(format)
2259 || IsVideo(srcImage.format) || IsVideo(format)
2260 || IsTypeless(srcImage.format) || IsTypeless(format) )
2261 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
2264 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
2265 return E_INVALIDARG;
2268 HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
2272 const Image *rimage = image.GetImage( 0, 0, 0 );
2279 WICPixelFormatGUID pfGUID;
2280 if ( _DXGIToWIC( srcImage.format, pfGUID ) )
2282 WICPixelFormatGUID targetGUID;
2283 if ( _DXGIToWIC( format, targetGUID ) )
2285 // Case 1: Both source and target formats are WIC supported
2286 hr = _ConvertUsingWIC( srcImage, pfGUID, targetGUID, filter, threshold, *rimage );
2290 // Case 2: Source format is supported by WIC, but not the target format
2291 hr = _ConvertFromWIC( srcImage, pfGUID, filter, threshold, *rimage );
2296 WICPixelFormatGUID targetGUID;
2297 if ( _DXGIToWIC( format, targetGUID ) )
2299 // Case 3: Source format is not supported by WIC, but does support the target format
2300 hr = _ConvertToWIC( srcImage, targetGUID, filter, threshold, *rimage );
2304 // Case 4: Both source and target format are not supported by WIC
2305 hr = _Convert( srcImage, filter, *rimage );
2319 //-------------------------------------------------------------------------------------
2320 // Convert image (complex)
2321 //-------------------------------------------------------------------------------------
2322 HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
2323 DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& result )
2325 if ( !srcImages || !nimages || (metadata.format == format) || !IsValid(format) )
2326 return E_INVALIDARG;
2328 if ( IsCompressed(metadata.format) || IsCompressed(format)
2329 || IsVideo(metadata.format) || IsVideo(format)
2330 || IsTypeless(metadata.format) || IsTypeless(format) )
2331 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
2334 if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
2335 return E_INVALIDARG;
2338 TexMetadata mdata2 = metadata;
2339 mdata2.format = format;
2340 HRESULT hr = result.Initialize( mdata2 );
2344 if ( nimages != result.GetImageCount() )
2350 const Image* dest = result.GetImages();
2357 WICPixelFormatGUID pfGUID, targetGUID;
2358 bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
2359 bool wictargetpf = _DXGIToWIC( format, targetGUID );
2361 for( size_t index=0; index < nimages; ++index )
2363 const Image& src = srcImages[ index ];
2364 if ( src.format != metadata.format )
2371 if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
2375 const Image& dst = dest[ index ];
2376 assert( dst.format == format );
2378 if ( src.width != dst.width || src.height != dst.height )
2388 // Case 1: Both source and target formats are WIC supported
2389 hr = _ConvertUsingWIC( src, pfGUID, targetGUID, filter, threshold, dst );
2393 // Case 2: Source format is supported by WIC, but not the target format
2394 hr = _ConvertFromWIC( src, pfGUID, filter, threshold, dst );
2401 // Case 3: Source format is not supported by WIC, but does support the target format
2402 hr = _ConvertToWIC( src, targetGUID, filter, threshold, dst );
2406 // Case 4: Both source and target format are not supported by WIC
2407 hr = _Convert( src, filter, dst );