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" );
1810 static int __cdecl _ConvertCompare( const void* ptr1, const void *ptr2 )
1812 const ConvertData *p1 = reinterpret_cast<const ConvertData*>(ptr1);
1813 const ConvertData *p2 = reinterpret_cast<const ConvertData*>(ptr2);
1814 if ( p1->format == p2->format ) return 0;
1815 else return (p1->format < p2->format ) ? -1 : 1;
1818 DWORD _GetConvertFlags( DXGI_FORMAT format )
1821 // Ensure conversion table is in ascending order
1822 assert( _countof(g_ConvertTable) > 0 );
1823 DXGI_FORMAT lastvalue = g_ConvertTable[0].format;
1824 for( size_t index=1; index < _countof(g_ConvertTable); ++index )
1826 assert( g_ConvertTable[index].format > lastvalue );
1827 lastvalue = g_ConvertTable[index].format;
1831 ConvertData key = { format, 0 };
1832 const ConvertData* in = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1834 return (in) ? in->flags : 0;
1837 void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, DXGI_FORMAT inFormat, DWORD flags )
1839 assert( pBuffer && count > 0 && (((uintptr_t)pBuffer & 0xF) == 0) );
1840 assert( IsValid(outFormat) && !IsVideo(outFormat) && !IsTypeless(outFormat) );
1841 assert( IsValid(inFormat) && !IsVideo(inFormat) && !IsTypeless(inFormat) );
1847 // Ensure conversion table is in ascending order
1848 assert( _countof(g_ConvertTable) > 0 );
1849 DXGI_FORMAT lastvalue = g_ConvertTable[0].format;
1850 for( size_t index=1; index < _countof(g_ConvertTable); ++index )
1852 assert( g_ConvertTable[index].format > lastvalue );
1853 lastvalue = g_ConvertTable[index].format;
1857 // Determine conversion details about source and dest formats
1858 ConvertData key = { inFormat, 0 };
1859 const ConvertData* in = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1861 key.format = outFormat;
1862 const ConvertData* out = (const ConvertData*) bsearch( &key, g_ConvertTable, _countof(g_ConvertTable), sizeof(ConvertData),
1870 assert( _GetConvertFlags( inFormat ) == in->flags );
1871 assert( _GetConvertFlags( outFormat ) == out->flags );
1873 // Handle SRGB filtering modes
1874 if ( IsSRGB( inFormat ) )
1875 flags |= TEX_FILTER_SRGB_IN;
1877 if ( IsSRGB( outFormat ) )
1878 flags |= TEX_FILTER_SRGB_OUT;
1880 if ( in->flags & CONVF_SNORM )
1881 flags &= ~TEX_FILTER_SRGB_IN;
1883 if ( out->flags & CONVF_SNORM )
1884 flags &= ~TEX_FILTER_SRGB_OUT;
1886 if ( (flags & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
1888 flags &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
1891 // sRGB input processing (sRGB -> RGB)
1892 if ( flags & TEX_FILTER_SRGB_IN )
1894 if ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) )
1896 XMVECTOR* ptr = pBuffer;
1897 for( size_t i=0; i < count; ++i )
1899 // rgb = rgb^(2.2); a=a
1901 XMVECTOR v1 = _TableDecodeGamma22( v );
1902 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
1907 // Handle conversion special cases
1908 DWORD diffFlags = in->flags ^ out->flags;
1909 if ( diffFlags != 0)
1911 if ( out->flags & CONVF_UNORM )
1913 if ( in->flags & CONVF_SNORM )
1916 XMVECTOR* ptr = pBuffer;
1917 for( size_t i=0; i < count; ++i )
1920 *ptr++ = XMVectorMultiplyAdd( v, g_XMOneHalf, g_XMOneHalf );
1923 else if ( in->flags & CONVF_FLOAT )
1926 XMVECTOR* ptr = pBuffer;
1927 for( size_t i=0; i < count; ++i )
1930 *ptr++ = XMVectorSaturate( v );
1934 else if ( out->flags & CONVF_SNORM )
1936 if ( in->flags & CONVF_UNORM )
1939 static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
1940 XMVECTOR* ptr = pBuffer;
1941 for( size_t i=0; i < count; ++i )
1944 *ptr++ = XMVectorMultiplyAdd( v, two, g_XMNegativeOne );
1947 else if ( in->flags & CONVF_FLOAT )
1950 XMVECTOR* ptr = pBuffer;
1951 for( size_t i=0; i < count; ++i )
1954 *ptr++ = XMVectorClamp( v, g_XMNegativeOne, g_XMOne );
1959 // !CONVF_A -> CONVF_A is handled because LoadScanline ensures alpha defaults to 1.0 for no-alpha formats
1961 // CONVF_PACKED cases are handled because LoadScanline/StoreScanline handles packing/unpacking
1963 if ( ((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A) )
1965 // !CONVF_A -> A format
1966 XMVECTOR* ptr = pBuffer;
1967 for( size_t i=0; i < count; ++i )
1970 *ptr++ = XMVectorSplatX( v );
1973 else if ( ((in->flags & CONVF_RGBA_MASK) == CONVF_A) && !(out->flags & CONVF_A) )
1975 // A format -> !CONVF_A
1976 XMVECTOR* ptr = pBuffer;
1977 for( size_t i=0; i < count; ++i )
1980 *ptr++ = XMVectorSplatW( v );
1983 else if ( ((in->flags & CONVF_RGB_MASK) == CONVF_R) && ((out->flags & CONVF_RGB_MASK) == (CONVF_R|CONVF_G|CONVF_B)) )
1985 // R format -> RGB format
1986 XMVECTOR* ptr = pBuffer;
1987 for( size_t i=0; i < count; ++i )
1990 XMVECTOR v1 = XMVectorSplatX( v );
1991 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
1996 // sRGB output processing (RGB -> sRGB)
1997 if ( flags & TEX_FILTER_SRGB_OUT )
1999 if ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) )
2001 XMVECTOR* ptr = pBuffer;
2002 for( size_t i=0; i < count; ++i )
2004 // rgb = rgb^(1/2.2); a=a
2006 XMVECTOR v1 = _TableEncodeGamma22( v );
2007 *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 );
2014 //-------------------------------------------------------------------------------------
2015 // Convert the source image using WIC
2016 //-------------------------------------------------------------------------------------
2017 static HRESULT _ConvertUsingWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
2018 _In_ const WICPixelFormatGUID& targetGUID,
2019 _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
2021 assert( srcImage.width == destImage.width );
2022 assert( srcImage.height == destImage.height );
2024 IWICImagingFactory* pWIC = _GetWIC();
2026 return E_NOINTERFACE;
2028 ScopedObject<IWICFormatConverter> FC;
2029 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2033 // Need to implement usage of TEX_FILTER_SRGB_IN/TEX_FILTER_SRGB_OUT
2035 BOOL canConvert = FALSE;
2036 hr = FC->CanConvert( pfGUID, targetGUID, &canConvert );
2037 if ( FAILED(hr) || !canConvert )
2039 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2040 return E_UNEXPECTED;
2043 ScopedObject<IWICBitmap> source;
2044 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
2045 static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
2046 srcImage.pixels, &source );
2050 hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2054 hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
2062 //-------------------------------------------------------------------------------------
2063 // Convert the source using WIC and then convert to DXGI format from there
2064 //-------------------------------------------------------------------------------------
2065 static HRESULT _ConvertFromWIC( _In_ const Image& srcImage, _In_ const WICPixelFormatGUID& pfGUID,
2066 _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
2068 assert( srcImage.width == destImage.width );
2069 assert( srcImage.height == destImage.height );
2071 IWICImagingFactory* pWIC = _GetWIC();
2073 return E_NOINTERFACE;
2075 ScopedObject<IWICFormatConverter> FC;
2076 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2080 BOOL canConvert = FALSE;
2081 hr = FC->CanConvert( pfGUID, GUID_WICPixelFormat128bppRGBAFloat, &canConvert );
2082 if ( FAILED(hr) || !canConvert )
2084 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2085 return E_UNEXPECTED;
2089 hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2093 const Image *timg = temp.GetImage( 0, 0, 0 );
2097 ScopedObject<IWICBitmap> source;
2098 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
2099 static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
2100 srcImage.pixels, &source );
2104 hr = FC->Initialize( source.Get(), GUID_WICPixelFormat128bppRGBAFloat, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2108 hr = FC->CopyPixels( 0, static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ), timg->pixels );
2112 // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format to final image
2113 uint8_t *pSrc = timg->pixels;
2114 uint8_t *pDest = destImage.pixels;
2115 if ( !pSrc || !pDest )
2118 for( size_t h = 0; h < srcImage.height; ++h )
2120 _ConvertScanline( reinterpret_cast<XMVECTOR*>(pSrc), srcImage.width, destImage.format, DXGI_FORMAT_R32G32B32A32_FLOAT, filter );
2122 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, reinterpret_cast<const XMVECTOR*>(pSrc), srcImage.width ) )
2125 pSrc += timg->rowPitch;
2126 pDest += destImage.rowPitch;
2133 //-------------------------------------------------------------------------------------
2134 // Convert the source from DXGI format then use WIC to convert to final format
2135 //-------------------------------------------------------------------------------------
2136 static HRESULT _ConvertToWIC( _In_ const Image& srcImage,
2137 _In_ const WICPixelFormatGUID& targetGUID, _In_ DWORD filter, _In_ float threshold, _In_ const Image& destImage )
2139 assert( srcImage.width == destImage.width );
2140 assert( srcImage.height == destImage.height );
2142 IWICImagingFactory* pWIC = _GetWIC();
2144 return E_NOINTERFACE;
2146 ScopedObject<IWICFormatConverter> FC;
2147 HRESULT hr = pWIC->CreateFormatConverter( &FC );
2151 BOOL canConvert = FALSE;
2152 hr = FC->CanConvert( GUID_WICPixelFormat128bppRGBAFloat, targetGUID, &canConvert );
2153 if ( FAILED(hr) || !canConvert )
2155 // This case is not an issue for the subset of WIC formats that map directly to DXGI
2156 return E_UNEXPECTED;
2160 hr = temp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
2164 const Image *timg = temp.GetImage( 0, 0, 0 );
2168 const uint8_t *pSrc = srcImage.pixels;
2172 uint8_t *pDest = timg->pixels;
2176 for( size_t h = 0; h < srcImage.height; ++h )
2178 if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2181 _ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
2183 pSrc += srcImage.rowPitch;
2184 pDest += timg->rowPitch;
2187 // Perform conversion on temp image which is now in R32G32B32A32_FLOAT format
2188 ScopedObject<IWICBitmap> source;
2189 hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( timg->width ), static_cast<UINT>( timg->height ), GUID_WICPixelFormat128bppRGBAFloat,
2190 static_cast<UINT>( timg->rowPitch ), static_cast<UINT>( timg->slicePitch ),
2191 timg->pixels, &source );
2195 hr = FC->Initialize( source.Get(), targetGUID, _GetWICDither( filter ), 0, threshold, WICBitmapPaletteTypeCustom );
2199 hr = FC->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
2207 //-------------------------------------------------------------------------------------
2208 // Convert the source image (not using WIC)
2209 //-------------------------------------------------------------------------------------
2210 static HRESULT _Convert( _In_ const Image& srcImage, _In_ DWORD filter, _In_ const Image& destImage )
2212 assert( srcImage.width == destImage.width );
2213 assert( srcImage.height == destImage.height );
2215 ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
2217 return E_OUTOFMEMORY;
2219 const uint8_t *pSrc = srcImage.pixels;
2220 uint8_t *pDest = destImage.pixels;
2221 if ( !pSrc || !pDest )
2224 for( size_t h = 0; h < srcImage.height; ++h )
2226 if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
2229 _ConvertScanline( scanline.get(), srcImage.width, destImage.format, srcImage.format, filter );
2231 if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
2234 pSrc += srcImage.rowPitch;
2235 pDest += destImage.rowPitch;
2242 //=====================================================================================
2244 //=====================================================================================
2246 //-------------------------------------------------------------------------------------
2248 //-------------------------------------------------------------------------------------
2249 HRESULT Convert( const Image& srcImage, DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& image )
2251 if ( (srcImage.format == format) || !IsValid( format ) )
2252 return E_INVALIDARG;
2254 if ( !srcImage.pixels )
2257 if ( IsCompressed(srcImage.format) || IsCompressed(format)
2258 || IsVideo(srcImage.format) || IsVideo(format)
2259 || IsTypeless(srcImage.format) || IsTypeless(format) )
2260 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
2263 if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
2264 return E_INVALIDARG;
2267 HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
2271 const Image *rimage = image.GetImage( 0, 0, 0 );
2278 WICPixelFormatGUID pfGUID;
2279 if ( _DXGIToWIC( srcImage.format, pfGUID ) )
2281 WICPixelFormatGUID targetGUID;
2282 if ( _DXGIToWIC( format, targetGUID ) )
2284 // Case 1: Both source and target formats are WIC supported
2285 hr = _ConvertUsingWIC( srcImage, pfGUID, targetGUID, filter, threshold, *rimage );
2289 // Case 2: Source format is supported by WIC, but not the target format
2290 hr = _ConvertFromWIC( srcImage, pfGUID, filter, threshold, *rimage );
2295 WICPixelFormatGUID targetGUID;
2296 if ( _DXGIToWIC( format, targetGUID ) )
2298 // Case 3: Source format is not supported by WIC, but does support the target format
2299 hr = _ConvertToWIC( srcImage, targetGUID, filter, threshold, *rimage );
2303 // Case 4: Both source and target format are not supported by WIC
2304 hr = _Convert( srcImage, filter, *rimage );
2318 //-------------------------------------------------------------------------------------
2319 // Convert image (complex)
2320 //-------------------------------------------------------------------------------------
2321 HRESULT Convert( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
2322 DXGI_FORMAT format, DWORD filter, float threshold, ScratchImage& result )
2324 if ( !srcImages || !nimages || (metadata.format == format) || !IsValid(format) )
2325 return E_INVALIDARG;
2327 if ( IsCompressed(metadata.format) || IsCompressed(format)
2328 || IsVideo(metadata.format) || IsVideo(format)
2329 || IsTypeless(metadata.format) || IsTypeless(format) )
2330 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
2333 if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
2334 return E_INVALIDARG;
2337 TexMetadata mdata2 = metadata;
2338 mdata2.format = format;
2339 HRESULT hr = result.Initialize( mdata2 );
2343 if ( nimages != result.GetImageCount() )
2349 const Image* dest = result.GetImages();
2356 WICPixelFormatGUID pfGUID, targetGUID;
2357 bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
2358 bool wictargetpf = _DXGIToWIC( format, targetGUID );
2360 for( size_t index=0; index < nimages; ++index )
2362 const Image& src = srcImages[ index ];
2363 if ( src.format != metadata.format )
2370 if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
2374 const Image& dst = dest[ index ];
2375 assert( dst.format == format );
2377 if ( src.width != dst.width || src.height != dst.height )
2387 // Case 1: Both source and target formats are WIC supported
2388 hr = _ConvertUsingWIC( src, pfGUID, targetGUID, filter, threshold, dst );
2392 // Case 2: Source format is supported by WIC, but not the target format
2393 hr = _ConvertFromWIC( src, pfGUID, filter, threshold, dst );
2400 // Case 3: Source format is not supported by WIC, but does support the target format
2401 hr = _ConvertToWIC( src, targetGUID, filter, threshold, dst );
2405 // Case 4: Both source and target format are not supported by WIC
2406 hr = _Convert( src, filter, dst );