69 { DXGI_FORMAT_BC4_UNORM,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC,
MAKEFOURCC(
'A',
'T',
'I',
'1' ), 0, 0, 0, 0, 0 } },
70 { DXGI_FORMAT_BC5_UNORM,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC,
MAKEFOURCC(
'A',
'T',
'I',
'2' ), 0, 0, 0, 0, 0 } },
81 { DXGI_FORMAT_R10G10B10A2_UNORM,
CONV_FLAGS_SWIZZLE, {
sizeof(
DDS_PIXELFORMAT),
DDS_RGB, 0, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 } },
82 { DXGI_FORMAT_R10G10B10A2_UNORM,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_RGB, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 } },
104 { DXGI_FORMAT_R16G16B16A16_UNORM,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 36, 0, 0, 0, 0, 0 } },
105 { DXGI_FORMAT_R16G16B16A16_SNORM,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 110, 0, 0, 0, 0, 0 } },
106 { DXGI_FORMAT_R16_FLOAT,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 111, 0, 0, 0, 0, 0 } },
107 { DXGI_FORMAT_R16G16_FLOAT,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 112, 0, 0, 0, 0, 0 } },
108 { DXGI_FORMAT_R16G16B16A16_FLOAT,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 113, 0, 0, 0, 0, 0 } },
109 { DXGI_FORMAT_R32_FLOAT,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 114, 0, 0, 0, 0, 0 } },
110 { DXGI_FORMAT_R32G32_FLOAT,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 115, 0, 0, 0, 0, 0 } },
111 { DXGI_FORMAT_R32G32B32A32_FLOAT,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC, 116, 0, 0, 0, 0, 0 } },
113 { DXGI_FORMAT_R32_FLOAT,
CONV_FLAGS_NONE, {
sizeof(
DDS_PIXELFORMAT),
DDS_RGB, 0, 32, 0xffffffff, 0x00000000, 0x00000000, 0x00000000 } },
128 { DXGI_FORMAT_YUY2,
CONV_FLAGS_SWIZZLE, {
sizeof(
DDS_PIXELFORMAT),
DDS_FOURCC,
MAKEFOURCC(
'U',
'Y',
'V',
'Y'), 0, 0, 0, 0, 0 } },
148 for( index = 0; index < MAP_SIZE; ++index )
176 if ( index >= MAP_SIZE )
177 return DXGI_FORMAT_UNKNOWN;
183 return DXGI_FORMAT_UNKNOWN;
200 _Inout_ DWORD& convFlags )
207 if ( size < (
sizeof(
DDS_HEADER) +
sizeof(uint32_t)) )
209 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
213 uint32_t dwMagicNumber = *
reinterpret_cast<const uint32_t*
>(pSource);
219 auto pHeader =
reinterpret_cast<const DDS_HEADER*
>( (
const uint8_t*)pSource +
sizeof( uint32_t ) );
228 metadata.mipLevels = pHeader->dwMipMapCount;
229 if ( metadata.mipLevels == 0 )
230 metadata.mipLevels = 1;
234 && (
MAKEFOURCC(
'D',
'X',
'1',
'0' ) == pHeader->ddspf.dwFourCC) )
245 metadata.arraySize = d3d10ext->arraySize;
246 if ( metadata.arraySize == 0 )
248 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
251 metadata.format = d3d10ext->dxgiFormat;
254 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
261 switch ( d3d10ext->resourceDimension )
266 if ( (pHeader->dwFlags &
DDS_HEIGHT) && pHeader->dwHeight != 1 )
268 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
271 metadata.width = pHeader->dwWidth;
281 metadata.arraySize *= 6;
284 metadata.width = pHeader->dwWidth;
285 metadata.height = pHeader->dwHeight;
293 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
296 if ( metadata.arraySize > 1 )
297 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
299 metadata.width = pHeader->dwWidth;
300 metadata.height = pHeader->dwHeight;
301 metadata.depth = pHeader->dwDepth;
306 return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
317 metadata.miscFlags2 = d3d10ext->miscFlags2;
321 metadata.arraySize = 1;
325 metadata.width = pHeader->dwWidth;
326 metadata.height = pHeader->dwHeight;
327 metadata.depth = pHeader->dwDepth;
336 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
338 metadata.arraySize = 6;
342 metadata.width = pHeader->dwWidth;
343 metadata.height = pHeader->dwHeight;
350 metadata.format =
_GetDXGIFormat( pHeader->ddspf, flags, convFlags );
352 if ( metadata.format == DXGI_FORMAT_UNKNOWN )
353 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
361 switch ( metadata.format )
363 case DXGI_FORMAT_R8_UNORM:
364 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
368 case DXGI_FORMAT_R8G8_UNORM:
369 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
373 case DXGI_FORMAT_R16_UNORM:
374 metadata.format = DXGI_FORMAT_R16G16B16A16_UNORM;
384 switch ( metadata.format )
386 case DXGI_FORMAT_B8G8R8A8_UNORM:
387 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
391 case DXGI_FORMAT_B8G8R8X8_UNORM:
392 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
396 case DXGI_FORMAT_B8G8R8A8_TYPELESS:
397 metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
401 case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
402 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
406 case DXGI_FORMAT_B8G8R8X8_TYPELESS:
407 metadata.format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
411 case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
412 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
421 switch ( metadata.format )
423 case DXGI_FORMAT_B5G6R5_UNORM:
424 case DXGI_FORMAT_B5G5R5A1_UNORM:
425 case DXGI_FORMAT_B4G4R4A4_UNORM:
426 metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
428 if ( metadata.format == DXGI_FORMAT_B5G6R5_UNORM )
440 _Use_decl_annotations_
442 LPVOID pDestination,
size_t maxsize,
size_t& required )
448 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
469 case DXGI_FORMAT_R8G8B8A8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_A8B8G8R8,
sizeof(
DDS_PIXELFORMAT) );
break;
470 case DXGI_FORMAT_R16G16_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_G16R16,
sizeof(
DDS_PIXELFORMAT) );
break;
471 case DXGI_FORMAT_R8G8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_A8L8,
sizeof(
DDS_PIXELFORMAT) );
break;
472 case DXGI_FORMAT_R16_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_L16,
sizeof(
DDS_PIXELFORMAT) );
break;
473 case DXGI_FORMAT_R8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_L8,
sizeof(
DDS_PIXELFORMAT) );
break;
474 case DXGI_FORMAT_A8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_A8,
sizeof(
DDS_PIXELFORMAT) );
break;
475 case DXGI_FORMAT_R8G8_B8G8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_R8G8_B8G8,
sizeof(
DDS_PIXELFORMAT) );
break;
476 case DXGI_FORMAT_G8R8_G8B8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_G8R8_G8B8,
sizeof(
DDS_PIXELFORMAT) );
break;
477 case DXGI_FORMAT_BC1_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_DXT1,
sizeof(
DDS_PIXELFORMAT) );
break;
478 case DXGI_FORMAT_BC2_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), metadata.
IsPMAlpha() ? (&DDSPF_DXT2) : (&DDSPF_DXT3),
sizeof(
DDS_PIXELFORMAT) );
break;
479 case DXGI_FORMAT_BC3_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), metadata.
IsPMAlpha() ? (&DDSPF_DXT4) : (&DDSPF_DXT5),
sizeof(
DDS_PIXELFORMAT) );
break;
480 case DXGI_FORMAT_BC4_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_BC4_UNORM,
sizeof(
DDS_PIXELFORMAT) );
break;
481 case DXGI_FORMAT_BC4_SNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_BC4_SNORM,
sizeof(
DDS_PIXELFORMAT) );
break;
482 case DXGI_FORMAT_BC5_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_BC5_UNORM,
sizeof(
DDS_PIXELFORMAT) );
break;
483 case DXGI_FORMAT_BC5_SNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_BC5_SNORM,
sizeof(
DDS_PIXELFORMAT) );
break;
484 case DXGI_FORMAT_B5G6R5_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_R5G6B5,
sizeof(
DDS_PIXELFORMAT) );
break;
485 case DXGI_FORMAT_B5G5R5A1_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_A1R5G5B5,
sizeof(
DDS_PIXELFORMAT) );
break;
486 case DXGI_FORMAT_B8G8R8A8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_A8R8G8B8,
sizeof(
DDS_PIXELFORMAT) );
break;
487 case DXGI_FORMAT_B8G8R8X8_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_X8R8G8B8,
sizeof(
DDS_PIXELFORMAT) );
break;
488 case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_A4R4G4B4,
sizeof(
DDS_PIXELFORMAT) );
break;
489 case DXGI_FORMAT_YUY2: memcpy_s( &ddpf,
sizeof(ddpf), &DDSPF_YUY2,
sizeof(
DDS_PIXELFORMAT) );
break;
492 case DXGI_FORMAT_R32G32B32A32_FLOAT:
495 case DXGI_FORMAT_R16G16B16A16_FLOAT:
498 case DXGI_FORMAT_R16G16B16A16_UNORM:
501 case DXGI_FORMAT_R16G16B16A16_SNORM:
504 case DXGI_FORMAT_R32G32_FLOAT:
507 case DXGI_FORMAT_R16G16_FLOAT:
510 case DXGI_FORMAT_R32_FLOAT:
513 case DXGI_FORMAT_R16_FLOAT:
519 required =
sizeof(uint32_t) +
sizeof(
DDS_HEADER);
527 if ( maxsize < required )
528 return E_NOT_SUFFICIENT_BUFFER;
530 *
reinterpret_cast<uint32_t*
>(pDestination) =
DDS_MAGIC;
532 auto header =
reinterpret_cast<DDS_HEADER*
>(
reinterpret_cast<uint8_t*
>(pDestination) +
sizeof(uint32_t) );
549 header->dwMipMapCount =
static_cast<uint32_t
>( metadata.
mipLevels );
551 if ( header->dwMipMapCount > 1 )
559 if ( metadata.
width > 0xFFFFFFFF )
563 header->dwWidth =
static_cast<uint32_t
>( metadata.
width );
564 header->dwHeight = header->dwDepth = 1;
569 if ( metadata.
height > 0xFFFFFFFF
570 || metadata.
width > 0xFFFFFFFF)
574 header->dwHeight =
static_cast<uint32_t
>( metadata.
height );
575 header->dwWidth =
static_cast<uint32_t
>( metadata.
width );
587 if ( metadata.
height > 0xFFFFFFFF
588 || metadata.
width > 0xFFFFFFFF
589 || metadata.
depth > 0xFFFFFFFF )
595 header->dwHeight =
static_cast<uint32_t
>( metadata.
height );
596 header->dwWidth =
static_cast<uint32_t
>( metadata.
width );
597 header->dwDepth =
static_cast<uint32_t
>( metadata.
depth );
604 size_t rowPitch, slicePitch;
608 if ( slicePitch > 0xFFFFFFFF
609 || rowPitch > 0xFFFFFFFF )
616 header->dwPitchOrLinearSize =
static_cast<uint32_t
>( slicePitch );
621 header->dwPitchOrLinearSize =
static_cast<uint32_t
>( rowPitch );
626 memcpy_s( &header->ddspf,
sizeof(header->ddspf), &DDSPF_DX10,
sizeof(
DDS_PIXELFORMAT) );
632 ext->dxgiFormat = metadata.
format;
633 ext->resourceDimension = metadata.
dimension;
648 ext->arraySize =
static_cast<UINT
>( metadata.
arraySize / 6 );
652 ext->arraySize =
static_cast<UINT
>( metadata.
arraySize );
663 if ( flags & DDS_FLAGS_FORCE_DX10_EXT_MISC2 )
671 memcpy_s( &header->ddspf,
sizeof(header->ddspf), &ddpf,
sizeof(ddpf) );
726 static
bool _LegacyExpandScanline( _Out_writes_bytes_(
outSize) LPVOID pDestination,
size_t outSize, _In_ DXGI_FORMAT
outFormat,
730 assert( pDestination && outSize > 0 );
731 assert( pSource && inSize > 0 );
737 if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
741 if ( inSize >= 3 && outSize >= 4 )
743 const uint8_t * __restrict sPtr =
reinterpret_cast<const uint8_t*
>(pSource);
744 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
746 for(
size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 2 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 3, ocount += 4 )
749 uint32_t t1 = ( *(sPtr) << 16 );
750 uint32_t t2 = ( *(sPtr+1) << 8 );
751 uint32_t t3 = *(sPtr+2);
753 *(dPtr++) = t1 | t2 | t3 | 0xff000000;
763 case DXGI_FORMAT_R8G8B8A8_UNORM:
765 if ( inSize >= 1 && outSize >= 4 )
767 const uint8_t* __restrict sPtr =
reinterpret_cast<const uint8_t*
>(pSource);
768 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
770 for(
size_t ocount = 0, icount = 0; ( ( icount <
inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
774 uint32_t t1 = (t & 0xe0) | ((t & 0xe0) >> 3) | ((t & 0xc0) >> 6);
775 uint32_t t2 = ((t & 0x1c) << 11) | ((t & 0x1c) << 8) | ((t & 0x18) << 5);
776 uint32_t t3 = ((t & 0x03) << 22) | ((t & 0x03) << 20) | ((t & 0x03) << 18) | ((t & 0x03) << 16);
778 *(dPtr++) = t1 | t2 | t3 | 0xff000000;
784 case DXGI_FORMAT_B5G6R5_UNORM:
786 if ( inSize >= 1 && outSize >= 2 )
788 const uint8_t* __restrict sPtr =
reinterpret_cast<const uint8_t*
>(pSource);
789 uint16_t * __restrict dPtr =
reinterpret_cast<uint16_t*
>(pDestination);
791 for(
size_t ocount = 0, icount = 0; ( ( icount <
inSize ) && ( ocount < ( outSize - 1 ) ) ); ++icount, ocount += 2 )
795 uint16_t t1 = ((t & 0xe0) << 8) | ((t & 0xc0) << 5);
796 uint16_t t2 = ((t & 0x1c) << 6) | ((t & 0x1c) << 3);
797 uint16_t t3 = ((t & 0x03) << 3) | ((t & 0x03) << 1) | ((t & 0x02) >> 1);
799 *(dPtr++) = t1 | t2 | t3;
808 if ( outFormat != DXGI_FORMAT_R8G8B8A8_UNORM )
812 if ( inSize >= 2 && outSize >= 4 )
814 const uint16_t* __restrict sPtr =
reinterpret_cast<const uint16_t*
>(pSource);
815 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
817 for(
size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
819 uint16_t t = *(sPtr++);
821 uint32_t t1 = (t & 0x00e0) | ((t & 0x00e0) >> 3) | ((t & 0x00c0) >> 6);
822 uint32_t t2 = ((t & 0x001c) << 11) | ((t & 0x001c) << 8) | ((t & 0x0018) << 5);
823 uint32_t t3 = ((t & 0x0003) << 22) | ((t & 0x0003) << 20) | ((t & 0x0003) << 18) | ((t & 0x0003) << 16);
826 *(dPtr++) = t1 | t2 | t3 | ta;
833 if ( (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8 )
837 if ( inSize >= 1 && outSize >= 4 )
839 const uint8_t* __restrict sPtr =
reinterpret_cast<const uint8_t*
>(pSource);
840 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
842 for(
size_t ocount = 0, icount = 0; ( ( icount <
inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
846 *(dPtr++) = pal8[ t ];
853 if ( (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8 )
857 if ( inSize >= 2 && outSize >= 4 )
859 const uint16_t* __restrict sPtr =
reinterpret_cast<const uint16_t*
>(pSource);
860 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
862 for(
size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
864 uint16_t t = *(sPtr++);
866 uint32_t t1 = pal8[ t & 0xff ];
878 case DXGI_FORMAT_B4G4R4A4_UNORM :
880 if ( inSize >= 1 && outSize >= 2 )
882 const uint8_t * __restrict sPtr =
reinterpret_cast<const uint8_t*
>(pSource);
883 uint16_t * __restrict dPtr =
reinterpret_cast<uint16_t*
>(pDestination);
885 for(
size_t ocount = 0, icount = 0; ( ( icount <
inSize ) && ( ocount < ( outSize - 1 ) ) ); ++icount, ocount += 2 )
889 uint16_t t1 = (t & 0x0f);
892 *(dPtr++) = t1 | (t1 << 4) | (t1 << 8) | ta;
898 case DXGI_FORMAT_R8G8B8A8_UNORM:
900 if ( inSize >= 1 && outSize >= 4 )
902 const uint8_t * __restrict sPtr =
reinterpret_cast<const uint8_t*
>(pSource);
903 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
905 for(
size_t ocount = 0, icount = 0; ( ( icount <
inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
909 uint32_t t1 = ((t & 0x0f) << 4) | (t & 0x0f);
910 uint32_t ta = ( flags &
TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (((t & 0xf0) << 24) | ((t & 0xf0) << 20));
912 *(dPtr++) = t1 | (t1 << 8) | (t1 << 16) | ta;
921 if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
925 if ( inSize >= 2 && outSize >= 4 )
927 const uint16_t * __restrict sPtr =
reinterpret_cast<const uint16_t*
>(pSource);
928 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
930 for(
size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
932 uint16_t t = *(sPtr++);
934 uint32_t t1 = ((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8);
935 uint32_t t2 = ((t & 0x00f0) << 8) | ((t & 0x00f0) << 4);
936 uint32_t t3 = ((t & 0x000f) << 20) | ((t & 0x000f) << 16);
937 uint32_t ta = ( flags &
TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : (((t & 0xf000) << 16) | ((t & 0xf000) << 12));
939 *(dPtr++) = t1 | t2 | t3 | ta;
946 if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
950 if ( inSize >= 1 && outSize >= 4 )
952 const uint8_t * __restrict sPtr =
reinterpret_cast<const uint8_t*
>(pSource);
953 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
955 for(
size_t ocount = 0, icount = 0; ( ( icount <
inSize ) && ( ocount < ( outSize - 3 ) ) ); ++icount, ocount += 4 )
957 uint32_t t1 = *(sPtr++);
958 uint32_t t2 = (t1 << 8);
959 uint32_t t3 = (t1 << 16);
961 *(dPtr++) = t1 | t2 | t3 | 0xff000000;
968 if (outFormat != DXGI_FORMAT_R16G16B16A16_UNORM)
972 if ( inSize >= 2 && outSize >= 8 )
974 const uint16_t* __restrict sPtr =
reinterpret_cast<const uint16_t*
>(pSource);
975 uint64_t * __restrict dPtr =
reinterpret_cast<uint64_t*
>(pDestination);
977 for(
size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 7 ) ) ); icount += 2, ocount += 8 )
979 uint16_t t = *(sPtr++);
982 uint64_t t2 = (t1 << 16);
983 uint64_t t3 = (t1 << 32);
985 *(dPtr++) = t1 | t2 | t3 | 0xffff000000000000;
992 if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
996 if ( inSize >= 2 && outSize >= 4 )
998 const uint16_t* __restrict sPtr =
reinterpret_cast<const uint16_t*
>(pSource);
999 uint32_t * __restrict dPtr =
reinterpret_cast<uint32_t*
>(pDestination);
1001 for(
size_t ocount = 0, icount = 0; ( ( icount < ( inSize - 1 ) ) && ( ocount < ( outSize - 3 ) ) ); icount += 2, ocount += 4 )
1003 uint16_t t = *(sPtr++);
1005 uint32_t t1 = (t & 0xff);
1006 uint32_t t2 = (t1 << 8);
1007 uint32_t t3 = (t1 << 16);
1010 *(dPtr++) = t1 | t2 | t3 | ta;
1028 assert( image.GetPixels() );
1045 if ( (nimages == 0) || (nimages != image.GetImageCount()) )
1050 assert( pixelSize <= size );
1052 std::unique_ptr<Image[]> timages(
new (std::nothrow)
Image[nimages] );
1055 return E_OUTOFMEMORY;
1063 if ( nimages != image.GetImageCount() )
1068 const Image* images = image.GetImages();
1075 if ( convFlags & CONV_FLAGS_SWIZZLE )
1078 switch (metadata.dimension)
1084 for(
size_t item = 0; item < metadata.arraySize; ++item )
1086 for(
size_t level = 0; level < metadata.mipLevels; ++level, ++index )
1088 if ( index >= nimages )
1091 if ( images[ index ].height != timages[ index ].height )
1094 size_t dpitch = images[ index ].
rowPitch;
1095 size_t spitch = timages[ index ].rowPitch;
1097 const uint8_t *pSrc =
const_cast<const uint8_t*
>( timages[ index ].pixels );
1107 size_t csize = std::min<size_t>( images[ index ].
slicePitch, timages[ index ].slicePitch );
1108 memcpy_s( pDest, images[ index ].slicePitch, pSrc, csize );
1110 else if (
IsPlanar( metadata.format ) )
1114 return E_UNEXPECTED;
1116 size_t csize = std::min<size_t>( dpitch, spitch );
1117 for(
size_t h = 0; h <
count; ++h )
1119 memcpy_s( pDest, dpitch, pSrc, csize );
1126 for(
size_t h = 0; h < images[ index ].
height; ++h )
1128 if ( convFlags & CONV_FLAGS_EXPAND )
1134 (convFlags &
CONV_FLAGS_565) ? DXGI_FORMAT_B5G6R5_UNORM : DXGI_FORMAT_B5G5R5A1_UNORM,
1141 if ( !_LegacyExpandScanline( pDest, dpitch, metadata.format,
1142 pSrc, spitch, lformat, pal8,
1147 else if ( convFlags & CONV_FLAGS_SWIZZLE )
1150 metadata.format, tflags );
1155 metadata.format, tflags );
1170 size_t d = metadata.depth;
1172 for(
size_t level = 0; level < metadata.mipLevels; ++level )
1174 for(
size_t slice = 0; slice < d; ++slice, ++index )
1176 if ( index >= nimages )
1179 if ( images[ index ].height != timages[ index ].height )
1182 size_t dpitch = images[ index ].
rowPitch;
1183 size_t spitch = timages[ index ].rowPitch;
1185 const uint8_t *pSrc =
const_cast<const uint8_t*
>( timages[ index ].pixels );
1195 size_t csize = std::min<size_t>( images[ index ].
slicePitch, timages[ index ].slicePitch );
1196 memcpy_s( pDest, images[ index ].slicePitch, pSrc, csize );
1198 else if (
IsPlanar( metadata.format ) )
1201 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
1205 for(
size_t h = 0; h < images[ index ].
height; ++h )
1207 if ( convFlags & CONV_FLAGS_EXPAND )
1213 (convFlags &
CONV_FLAGS_565) ? DXGI_FORMAT_B5G6R5_UNORM : DXGI_FORMAT_B5G5R5A1_UNORM,
1220 if ( !_LegacyExpandScanline( pDest, dpitch, metadata.format,
1221 pSrc, spitch, lformat, pal8,
1226 else if ( convFlags & CONV_FLAGS_SWIZZLE )
1232 _CopyScanline( pDest, dpitch, pSrc, spitch, metadata.format, tflags );
1256 if ( !image.GetPixels() )
1259 const Image* images = image.GetImages();
1263 const TexMetadata& metadata = image.GetMetadata();
1266 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
1269 if ( convFlags & CONV_FLAGS_SWIZZLE )
1272 for(
size_t i = 0; i < image.GetImageCount(); ++i )
1274 const Image* img = &images[ i ];
1281 for(
size_t h = 0; h < img->
height; ++h )
1283 if ( convFlags & CONV_FLAGS_SWIZZLE )
1292 pPixels += rowPitch;
1308 _Use_decl_annotations_
1311 if ( !pSource || size == 0 )
1312 return E_INVALIDARG;
1314 DWORD convFlags = 0;
1318 _Use_decl_annotations_
1322 return E_INVALIDARG;
1324 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
1328 FILE_FLAG_SEQUENTIAL_SCAN, 0 ) ) );
1332 return HRESULT_FROM_WIN32( GetLastError() );
1336 LARGE_INTEGER fileSize = {0};
1338 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
1339 FILE_STANDARD_INFO fileInfo;
1340 if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo,
sizeof(fileInfo) ) )
1342 return HRESULT_FROM_WIN32( GetLastError() );
1344 fileSize = fileInfo.EndOfFile;
1346 if ( !GetFileSizeEx( hFile.get(), &fileSize ) )
1348 return HRESULT_FROM_WIN32( GetLastError() );
1353 if ( fileSize.HighPart > 0 )
1355 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
1359 if ( fileSize.LowPart < (
sizeof(
DDS_HEADER) +
sizeof(uint32_t) ) )
1366 uint8_t header[MAX_HEADER_SIZE];
1368 DWORD bytesRead = 0;
1369 if ( !ReadFile( hFile.get(), header, MAX_HEADER_SIZE, &bytesRead, 0 ) )
1371 return HRESULT_FROM_WIN32( GetLastError() );
1374 DWORD convFlags = 0;
1382 _Use_decl_annotations_
1385 if ( !pSource || size == 0 )
1386 return E_INVALIDARG;
1390 DWORD convFlags = 0;
1396 size_t offset =
sizeof(uint32_t) +
sizeof(
DDS_HEADER);
1400 assert( offset <= size );
1402 const uint32_t *pal8 =
nullptr;
1405 pal8 =
reinterpret_cast<const uint32_t*
>(
reinterpret_cast<const uint8_t*
>(pSource) + offset );
1407 offset += ( 256 *
sizeof(uint32_t) );
1408 if ( size < offset )
1416 auto pPixels =
reinterpret_cast<LPCVOID
>(
reinterpret_cast<const uint8_t*
>(pSource) + offset );
1418 hr =
_CopyImage( pPixels, size - offset, mdata,
1435 _Use_decl_annotations_
1439 return E_INVALIDARG;
1443 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
1447 FILE_FLAG_SEQUENTIAL_SCAN, 0 ) ) );
1452 return HRESULT_FROM_WIN32( GetLastError() );
1456 LARGE_INTEGER fileSize = {0};
1458 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
1459 FILE_STANDARD_INFO fileInfo;
1460 if ( !GetFileInformationByHandleEx( hFile.get(), FileStandardInfo, &fileInfo,
sizeof(fileInfo) ) )
1462 return HRESULT_FROM_WIN32( GetLastError() );
1464 fileSize = fileInfo.EndOfFile;
1466 if ( !GetFileSizeEx( hFile.get(), &fileSize ) )
1468 return HRESULT_FROM_WIN32( GetLastError() );
1473 if ( fileSize.HighPart > 0 )
1475 return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
1479 if ( fileSize.LowPart < (
sizeof(
DDS_HEADER) +
sizeof(uint32_t) ) )
1486 uint8_t header[MAX_HEADER_SIZE];
1488 DWORD bytesRead = 0;
1489 if ( !ReadFile( hFile.get(), header, MAX_HEADER_SIZE, &bytesRead, 0 ) )
1491 return HRESULT_FROM_WIN32( GetLastError() );
1494 DWORD convFlags = 0;
1496 HRESULT hr =
_DecodeDDSHeader( header, bytesRead, flags, mdata, convFlags );
1500 DWORD offset = MAX_HEADER_SIZE;
1505 LARGE_INTEGER filePos = {
sizeof(uint32_t) +
sizeof(
DDS_HEADER), 0};
1506 if ( !SetFilePointerEx( hFile.get(), filePos, 0, FILE_BEGIN ) )
1508 return HRESULT_FROM_WIN32( GetLastError() );
1511 offset =
sizeof(uint32_t) +
sizeof(
DDS_HEADER);
1514 std::unique_ptr<uint32_t[]> pal8;
1517 pal8.reset(
new (std::nothrow) uint32_t[256] );
1520 return E_OUTOFMEMORY;
1523 if ( !ReadFile( hFile.get(), pal8.get(), 256 *
sizeof(uint32_t), &bytesRead, 0 ) )
1525 return HRESULT_FROM_WIN32( GetLastError() );
1528 if ( bytesRead != (256 *
sizeof(uint32_t)) )
1533 offset += ( 256 *
sizeof(uint32_t) );
1536 DWORD remaining = fileSize.LowPart - offset;
1537 if ( remaining == 0 )
1546 std::unique_ptr<uint8_t[]> temp(
new (std::nothrow)
uint8_t[ remaining ] );
1550 return E_OUTOFMEMORY;
1553 if ( !ReadFile( hFile.get(), temp.get(), remaining, &bytesRead, 0 ) )
1556 return HRESULT_FROM_WIN32( GetLastError() );
1559 if ( bytesRead != remaining )
1565 hr =
_CopyImage( temp.get(), remaining, mdata,
1567 convFlags, pal8.get(), image );
1582 if ( !ReadFile( hFile.get(), image.
GetPixels(),
static_cast<DWORD
>( image.
GetPixelsSize() ), &bytesRead, 0 ) )
1585 return HRESULT_FROM_WIN32( GetLastError() );
1610 _Use_decl_annotations_
1613 if ( !images || (nimages == 0) )
1614 return E_INVALIDARG;
1617 size_t required = 0;
1622 bool fastpath =
true;
1624 for(
size_t i = 0; i < nimages; ++i )
1626 if ( !images[ i ].pixels )
1632 size_t ddsRowPitch, ddsSlicePitch;
1635 assert( images[ i ].rowPitch > 0 );
1636 assert( images[ i ].slicePitch > 0 );
1638 if ( ( images[ i ].rowPitch != ddsRowPitch ) || ( images[ i ].slicePitch != ddsSlicePitch ) )
1643 required += ddsSlicePitch;
1665 pDestination += required;
1679 for(
size_t item = 0; item < metadata.
arraySize; ++item )
1681 for(
size_t level = 0; level < metadata.
mipLevels; ++level )
1683 if ( index >= nimages )
1692 if ( memcpy_s( pDestination, remaining, images[ index ].pixels, pixsize ) )
1698 pDestination += pixsize;
1699 remaining -= pixsize;
1703 size_t ddsRowPitch, ddsSlicePitch;
1706 size_t rowPitch = images[ index ].
rowPitch;
1709 uint8_t * __restrict dPtr =
reinterpret_cast<uint8_t*
>(pDestination);
1712 size_t csize = std::min<size_t>( rowPitch, ddsRowPitch );
1713 size_t tremaining = remaining;
1714 for(
size_t j = 0; j < lines; ++j )
1716 if ( memcpy_s( dPtr, tremaining, sPtr, csize ) )
1723 dPtr += ddsRowPitch;
1724 tremaining -= ddsRowPitch;
1727 pDestination += ddsSlicePitch;
1728 remaining -= ddsSlicePitch;
1745 size_t d = metadata.
depth;
1748 for(
size_t level = 0; level < metadata.
mipLevels; ++level )
1750 for(
size_t slice = 0; slice < d; ++slice )
1752 if ( index >= nimages )
1761 if ( memcpy_s( pDestination, remaining, images[ index ].pixels, pixsize ) )
1767 pDestination += pixsize;
1768 remaining -= pixsize;
1772 size_t ddsRowPitch, ddsSlicePitch;
1775 size_t rowPitch = images[ index ].
rowPitch;
1778 uint8_t * __restrict dPtr =
reinterpret_cast<uint8_t*
>(pDestination);
1781 size_t csize = std::min<size_t>( rowPitch, ddsRowPitch );
1782 size_t tremaining = remaining;
1783 for(
size_t j = 0; j < lines; ++j )
1785 if ( memcpy_s( dPtr, tremaining, sPtr, csize ) )
1792 dPtr += ddsRowPitch;
1793 tremaining -= ddsRowPitch;
1796 pDestination += ddsSlicePitch;
1797 remaining -= ddsSlicePitch;
1821 _Use_decl_annotations_
1825 return E_INVALIDARG;
1829 uint8_t header[MAX_HEADER_SIZE];
1831 HRESULT hr =
_EncodeDDSHeader( metadata, flags, header, MAX_HEADER_SIZE, required );
1836 #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
1843 return HRESULT_FROM_WIN32( GetLastError() );
1847 if ( !WriteFile( hFile.get(), header,
static_cast<DWORD
>( required ), &bytesWritten, 0 ) )
1849 return HRESULT_FROM_WIN32( GetLastError() );
1852 if ( bytesWritten != required )
1864 for(
size_t item = 0; item < metadata.
arraySize; ++item )
1866 for(
size_t level = 0; level < metadata.
mipLevels; ++level, ++index )
1868 if ( index >= nimages )
1871 if ( !images[ index ].pixels )
1874 assert( images[ index ].rowPitch > 0 );
1875 assert( images[ index ].slicePitch > 0 );
1877 size_t ddsRowPitch, ddsSlicePitch;
1880 if ( images[ index ].slicePitch == ddsSlicePitch )
1882 if ( !WriteFile( hFile.get(), images[ index ].
pixels,
static_cast<DWORD
>( ddsSlicePitch ), &bytesWritten, 0 ) )
1884 return HRESULT_FROM_WIN32( GetLastError() );
1887 if ( bytesWritten != ddsSlicePitch )
1894 size_t rowPitch = images[ index ].
rowPitch;
1895 if ( rowPitch < ddsRowPitch )
1904 for(
size_t j = 0; j < lines; ++j )
1906 if ( !WriteFile( hFile.get(), sPtr,
static_cast<DWORD
>( ddsRowPitch ), &bytesWritten, 0 ) )
1908 return HRESULT_FROM_WIN32( GetLastError() );
1911 if ( bytesWritten != ddsRowPitch )
1929 size_t d = metadata.
depth;
1932 for(
size_t level = 0; level < metadata.
mipLevels; ++level )
1934 for(
size_t slice = 0; slice < d; ++slice, ++index )
1936 if ( index >= nimages )
1939 if ( !images[ index ].pixels )
1942 assert( images[ index ].rowPitch > 0 );
1943 assert( images[ index ].slicePitch > 0 );
1945 size_t ddsRowPitch, ddsSlicePitch;
1948 if ( images[ index ].slicePitch == ddsSlicePitch )
1950 if ( !WriteFile( hFile.get(), images[ index ].
pixels,
static_cast<DWORD
>( ddsSlicePitch ), &bytesWritten, 0 ) )
1952 return HRESULT_FROM_WIN32( GetLastError() );
1955 if ( bytesWritten != ddsSlicePitch )
1962 size_t rowPitch = images[ index ].
rowPitch;
1963 if ( rowPitch < ddsRowPitch )
1972 for(
size_t j = 0; j < lines; ++j )
1974 if ( !WriteFile( hFile.get(), sPtr,
static_cast<DWORD
>( ddsRowPitch ), &bytesWritten, 0 ) )
1976 return HRESULT_FROM_WIN32( GetLastError() );
1979 if ( bytesWritten != ddsRowPitch )
_Use_decl_annotations_ HRESULT _EncodeDDSHeader(const TexMetadata &metadata, DWORD flags, LPVOID pDestination, size_t maxsize, size_t &required)
_In_ size_t _In_ const TexMetadata _In_ DWORD cpFlags
_Use_decl_annotations_ bool _ExpandScanline(LPVOID pDestination, size_t outSize, DXGI_FORMAT outFormat, LPCVOID pSource, size_t inSize, DXGI_FORMAT inFormat, DWORD flags)
bool IsPlanar(_In_ DXGI_FORMAT fmt)
#define DDS_CUBEMAP_ALLFACES
public std::unique_ptr< void, handle_closer > ScopedHandle
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_reads_opt_(256) const uint32_t *pal8
void _CopyScanline(_When_(pDestination==pSource, _Inout_updates_bytes_(outSize)) _When_(pDestination!=pSource, _Out_writes_bytes_(outSize)) LPVOID pDestination, _In_ size_t outSize, _In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize, _In_ DXGI_FORMAT format, _In_ DWORD flags)
const LegacyDDS g_LegacyDDSMap[]
size_t GetPixelsSize() const
#define DDS_SURFACE_FLAGS_CUBEMAP
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
HRESULT Initialize(_In_ size_t size)
HRESULT Initialize(_In_ const TexMetadata &mdata, _In_ DWORD flags=CP_FLAGS_NONE)
static DXGI_FORMAT _GetDXGIFormat(const DDS_PIXELFORMAT &ddpf, DWORD flags, _Inout_ DWORD &convFlags)
#define DDS_HEADER_FLAGS_MIPMAP
void * GetBufferPointer() const
HRESULT LoadFromDDSFile(_In_z_ LPCWSTR szFile, _In_ DWORD flags, _Out_opt_ TexMetadata *metadata, _Out_ ScratchImage &image)
#define MAKEFOURCC(ch0, ch1, ch2, ch3)
static HRESULT _CopyImage(_In_reads_bytes_(size) const void *pPixels, _In_ size_t size, _In_ const TexMetadata &metadata, _In_ DWORD cpFlags, _In_ DWORD convFlags, _In_reads_opt_(256) const uint32_t *pal8, _In_ const ScratchImage &image)
bool IsCompressed(_In_ DXGI_FORMAT fmt)
_In_ size_t _In_ const TexMetadata & metadata
#define DDS_HEADER_FLAGS_PITCH
_Use_decl_annotations_ void _SwizzleScanline(LPVOID pDestination, size_t outSize, LPCVOID pSource, size_t inSize, DXGI_FORMAT format, DWORD flags)
void ComputePitch(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _Out_ size_t &rowPitch, _Out_ size_t &slicePitch, _In_ DWORD flags=CP_FLAGS_NONE)
bool IsValid(_In_ DXGI_FORMAT fmt)
size_t _In_ DXGI_FORMAT outFormat
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT inFormat
size_t _In_ DXGI_FORMAT size_t inSize
bool IsPalettized(_In_ DXGI_FORMAT fmt)
HRESULT SaveToDDSFile(_In_ const Image &image, _In_ DWORD flags, _In_z_ LPCWSTR szFile)
_Use_decl_annotations_ void _DetermineImageArray(const TexMetadata &metadata, DWORD cpFlags, size_t &nImages, size_t &pixelSize)
static HRESULT _DecodeDDSHeader(_In_reads_bytes_(size) LPCVOID pSource, size_t size, DWORD flags, _Out_ TexMetadata &metadata, _Inout_ DWORD &convFlags)
size_t _In_ DXGI_FORMAT _In_reads_bytes_(inSize) LPCVOID pSource
#define DDS_HEADER_FLAGS_VOLUME
#define DDS_SURFACE_FLAGS_MIPMAP
#define DDS_HEADER_FLAGS_TEXTURE
HANDLE safe_handle(HANDLE h)
uint8_t * GetPixels() const
#define DDS_SURFACE_FLAGS_TEXTURE
HRESULT SaveToDDSMemory(_In_ const Image &image, _In_ DWORD flags, _Out_ Blob &blob)
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
_Success_(return!=false) static bool _LegacyExpandScanline(_Out_writes_bytes_(outSize) LPVOID pDestination
HRESULT GetMetadataFromDDSFile(_In_z_ LPCWSTR szFile, _In_ DWORD flags, _Out_ TexMetadata &metadata)
static HRESULT _CopyImageInPlace(DWORD convFlags, _In_ const ScratchImage &image)
_In_ size_t _In_ size_t size
static TEXP_LEGACY_FORMAT _FindLegacyFormat(DWORD flags)
_Use_decl_annotations_ bool _SetupImageArray(uint8_t *pMemory, size_t pixelSize, const TexMetadata &metadata, DWORD cpFlags, Image *images, size_t nImages)
HRESULT GetMetadataFromDDSMemory(_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags, _Out_ TexMetadata &metadata)
HRESULT LoadFromDDSMemory(_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags, _Out_opt_ TexMetadata *metadata, _Out_ ScratchImage &image)
size_t GetBufferSize() const
#define DDS_HEADER_FLAGS_LINEARSIZE
size_t ComputeScanlines(_In_ DXGI_FORMAT fmt, _In_ size_t height)