20 #pragma warning(disable : 4616 6993)
50 case DXGI_FORMAT_BC1_UNORM:
51 case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode =
nullptr; blocksize = 8; cflags = 0;
break;
52 case DXGI_FORMAT_BC2_UNORM:
53 case DXGI_FORMAT_BC2_UNORM_SRGB: pfEncode =
D3DXEncodeBC2; blocksize = 16; cflags = 0;
break;
54 case DXGI_FORMAT_BC3_UNORM:
55 case DXGI_FORMAT_BC3_UNORM_SRGB: pfEncode =
D3DXEncodeBC3; blocksize = 16; cflags = 0;
break;
60 case DXGI_FORMAT_BC6H_UF16: pfEncode =
D3DXEncodeBC6HU; blocksize = 16; cflags = 0;
break;
61 case DXGI_FORMAT_BC6H_SF16: pfEncode =
D3DXEncodeBC6HS; blocksize = 16; cflags = 0;
break;
62 case DXGI_FORMAT_BC7_UNORM:
63 case DXGI_FORMAT_BC7_UNORM_SRGB: pfEncode =
D3DXEncodeBC7; blocksize = 16; cflags = 0;
break;
64 default: pfEncode =
nullptr; blocksize = 0; cflags = 0;
return false;
73 _In_ DWORD srgb, _In_
float alphaRef )
75 if ( !image.pixels || !result.pixels )
78 assert( image.width == result.width );
79 assert( image.height == result.height );
81 const DXGI_FORMAT
format = image.format;
89 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
93 sbpp = ( sbpp + 7 ) / 8;
102 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
105 const uint8_t *pSrc = image.pixels;
106 const size_t rowPitch = image.rowPitch;
107 for(
size_t h=0; h < image.height; h += 4 )
111 size_t ph = std::min<size_t>( 4, image.height - h );
115 size_t pw = std::min<size_t>( 4, image.width - w );
116 assert( pw > 0 && ph > 0 );
118 if ( !
_LoadScanline( &temp[0], pw, sptr, rowPitch, format ) )
123 if ( !
_LoadScanline( &temp[4], pw, sptr + rowPitch, rowPitch, format ) )
128 if ( !
_LoadScanline( &temp[8], pw, sptr + rowPitch*2, rowPitch, format ) )
133 if ( !
_LoadScanline( &temp[12], pw, sptr + rowPitch*3, rowPitch, format ) )
139 if ( pw != 4 || ph != 4 )
142 static const size_t uSrc[] = { 0, 0, 0, 1 };
146 for(
size_t t = 0; t < ph && t < 4; ++t )
148 for(
size_t s = pw;
s < 4; ++
s )
150 #pragma prefast(suppress: 26000, "PREFAST false positive")
151 temp[ (t << 2) |
s ] = temp[ (t << 2) | uSrc[
s] ];
158 for(
size_t t = ph; t < 4; ++t )
160 for(
size_t s = 0;
s < 4; ++
s )
162 #pragma prefast(suppress: 26000, "PREFAST false positive")
163 temp[ (t << 2) |
s ] = temp[ (uSrc[t] << 2) |
s ];
172 pfEncode( dptr, temp, bcflags );
181 pDest += result.rowPitch;
190 static HRESULT _CompressBC_Parallel( _In_
const Image& image, _In_
const Image& result, _In_ DWORD bcflags,
191 _In_ DWORD srgb, _In_
float alphaRef )
193 if ( !image.pixels || !result.pixels )
196 assert( image.width == result.width );
197 assert( image.height == result.height );
199 const DXGI_FORMAT
format = image.format;
207 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
211 sbpp = ( sbpp + 7 ) / 8;
218 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
221 const size_t nBlocks = std::max<size_t>(1, (image.width + 3) / 4 ) * std::max<size_t>(1, (image.height + 3) / 4 );
225 #pragma omp parallel for
226 for(
int nb=0; nb < static_cast<int>( nBlocks ); ++nb )
228 const size_t nbWidth = std::max<size_t>(1, (image.width + 3) / 4 );
230 const size_t y = nb / nbWidth;
231 const size_t x = nb - (y*nbWidth);
233 assert( x < image.width && y < image.height );
235 size_t rowPitch = image.rowPitch;
236 const uint8_t *pSrc = image.pixels + (y*4*rowPitch) + (x*4*sbpp);
238 uint8_t *pDest = result.pixels + (nb*blocksize);
240 size_t ph = std::min<size_t>( 4, image.height -
y );
241 size_t pw = std::min<size_t>( 4, image.width - x );
242 assert( pw > 0 && ph > 0 );
245 if ( !
_LoadScanline( &temp[0], pw, pSrc, rowPitch, format ) )
250 if ( !
_LoadScanline( &temp[4], pw, pSrc + rowPitch, rowPitch, format ) )
255 if ( !
_LoadScanline( &temp[8], pw, pSrc + rowPitch*2, rowPitch, format ) )
260 if ( !
_LoadScanline( &temp[12], pw, pSrc + rowPitch*3, rowPitch, format ) )
266 if ( pw != 4 || ph != 4 )
269 static const size_t uSrc[] = { 0, 0, 0, 1 };
273 for(
size_t t = 0; t < ph && t < 4; ++t )
275 for(
size_t s = pw;
s < 4; ++
s )
277 temp[ (t << 2) |
s ] = temp[ (t << 2) | uSrc[
s] ];
284 for(
size_t t = ph; t < 4; ++t )
286 for(
size_t s = 0;
s < 4; ++
s )
288 temp[ (t << 2) |
s ] = temp[ (uSrc[t] << 2) |
s ];
297 pfEncode( pDest, temp, bcflags );
313 case DXGI_FORMAT_BC1_TYPELESS:
314 case DXGI_FORMAT_BC1_UNORM:
315 case DXGI_FORMAT_BC2_TYPELESS:
316 case DXGI_FORMAT_BC2_UNORM:
317 case DXGI_FORMAT_BC3_TYPELESS:
318 case DXGI_FORMAT_BC3_UNORM:
319 case DXGI_FORMAT_BC7_TYPELESS:
320 case DXGI_FORMAT_BC7_UNORM:
321 return DXGI_FORMAT_R8G8B8A8_UNORM;
323 case DXGI_FORMAT_BC1_UNORM_SRGB:
324 case DXGI_FORMAT_BC2_UNORM_SRGB:
325 case DXGI_FORMAT_BC3_UNORM_SRGB:
326 case DXGI_FORMAT_BC7_UNORM_SRGB:
327 return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
329 case DXGI_FORMAT_BC4_TYPELESS:
330 case DXGI_FORMAT_BC4_UNORM:
331 return DXGI_FORMAT_R8_UNORM;
333 case DXGI_FORMAT_BC4_SNORM:
334 return DXGI_FORMAT_R8_SNORM;
336 case DXGI_FORMAT_BC5_TYPELESS:
337 case DXGI_FORMAT_BC5_UNORM:
338 return DXGI_FORMAT_R8G8_UNORM;
340 case DXGI_FORMAT_BC5_SNORM:
341 return DXGI_FORMAT_R8G8_SNORM;
343 case DXGI_FORMAT_BC6H_TYPELESS:
344 case DXGI_FORMAT_BC6H_UF16:
345 case DXGI_FORMAT_BC6H_SF16:
348 return DXGI_FORMAT_R32G32B32A32_FLOAT;
351 return DXGI_FORMAT_UNKNOWN;
359 if ( !cImage.pixels || !result.pixels )
362 assert( cImage.width == result.width );
363 assert( cImage.height == result.height );
365 const DXGI_FORMAT format = result.format;
373 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
377 dbpp = ( dbpp + 7 ) / 8;
379 uint8_t *pDest = result.pixels;
385 switch( cImage.format )
387 case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM;
break;
388 case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM;
break;
389 case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM;
break;
390 case DXGI_FORMAT_BC4_TYPELESS: cformat = DXGI_FORMAT_BC4_UNORM;
break;
391 case DXGI_FORMAT_BC5_TYPELESS: cformat = DXGI_FORMAT_BC5_UNORM;
break;
392 case DXGI_FORMAT_BC6H_TYPELESS: cformat = DXGI_FORMAT_BC6H_UF16;
break;
393 case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM;
break;
394 default: cformat = cImage.format;
break;
402 case DXGI_FORMAT_BC1_UNORM:
403 case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode =
D3DXDecodeBC1; sbpp = 8;
break;
404 case DXGI_FORMAT_BC2_UNORM:
405 case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode =
D3DXDecodeBC2; sbpp = 16;
break;
406 case DXGI_FORMAT_BC3_UNORM:
407 case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode =
D3DXDecodeBC3; sbpp = 16;
break;
408 case DXGI_FORMAT_BC4_UNORM: pfDecode =
D3DXDecodeBC4U; sbpp = 8;
break;
409 case DXGI_FORMAT_BC4_SNORM: pfDecode =
D3DXDecodeBC4S; sbpp = 8;
break;
410 case DXGI_FORMAT_BC5_UNORM: pfDecode =
D3DXDecodeBC5U; sbpp = 16;
break;
411 case DXGI_FORMAT_BC5_SNORM: pfDecode =
D3DXDecodeBC5S; sbpp = 16;
break;
412 case DXGI_FORMAT_BC6H_UF16: pfDecode =
D3DXDecodeBC6HU; sbpp = 16;
break;
413 case DXGI_FORMAT_BC6H_SF16: pfDecode =
D3DXDecodeBC6HS; sbpp = 16;
break;
414 case DXGI_FORMAT_BC7_UNORM:
415 case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode =
D3DXDecodeBC7; sbpp = 16;
break;
417 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
421 const uint8_t *pSrc = cImage.pixels;
422 const size_t rowPitch = result.rowPitch;
423 for(
size_t h=0; h < cImage.height; h += 4 )
427 size_t ph = std::min<size_t>( 4, cImage.height - h );
429 for(
size_t count = 0;
count < cImage.rowPitch;
count += sbpp, w += 4 )
431 pfDecode( temp, sptr );
434 size_t pw = std::min<size_t>( 4, cImage.width - w );
435 assert( pw > 0 && ph > 0 );
442 if ( !
_StoreScanline( dptr + rowPitch, rowPitch, format, &temp[4], pw ) )
447 if ( !
_StoreScanline( dptr + rowPitch*2, rowPitch, format, &temp[8], pw ) )
452 if ( !
_StoreScanline( dptr + rowPitch*3, rowPitch, format, &temp[12], pw ) )
462 pSrc += cImage.rowPitch;
473 if ( !cImage.pixels )
478 switch( cImage.format )
480 case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM;
break;
481 case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM;
break;
482 case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM;
break;
483 case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM;
break;
484 default: cformat = cImage.format;
break;
492 case DXGI_FORMAT_BC1_UNORM:
493 case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode =
D3DXDecodeBC1; sbpp = 8;
break;
494 case DXGI_FORMAT_BC2_UNORM:
495 case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode =
D3DXDecodeBC2; sbpp = 16;
break;
496 case DXGI_FORMAT_BC3_UNORM:
497 case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode =
D3DXDecodeBC3; sbpp = 16;
break;
498 case DXGI_FORMAT_BC7_UNORM:
499 case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode =
D3DXDecodeBC7; sbpp = 16;
break;
506 static const XMVECTORF32
threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
509 const uint8_t *pPixels = cImage.pixels;
510 for(
size_t h = 0; h < cImage.height; h += 4 )
513 size_t ph = std::min<size_t>( 4, cImage.height - h );
515 for(
size_t count = 0;
count < cImage.rowPitch;
count += sbpp, w += 4 )
517 pfDecode( temp, ptr );
519 size_t pw = std::min<size_t>( 4, cImage.width - w );
520 assert( pw > 0 && ph > 0 );
522 if ( pw == 4 && ph == 4 )
525 for(
size_t j = 0; j < 16; ++j )
527 XMVECTOR alpha = XMVectorSplatW( temp[j] );
528 if ( XMVector4Less( alpha, threshold ) )
535 for(
size_t y = 0; y < ph; ++
y )
537 for(
size_t x = 0; x < pw; ++x )
539 XMVECTOR alpha = XMVectorSplatW( temp[ y * 4 + x ] );
540 if ( XMVector4Less( alpha, threshold ) )
549 pPixels += cImage.rowPitch;
563 _Use_decl_annotations_
571 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
605 _Use_decl_annotations_
607 DXGI_FORMAT format, DWORD compress,
float alphaRef,
ScratchImage& cImages )
609 if ( !srcImages || !nimages )
617 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
640 for(
size_t index=0; index < nimages; ++index )
642 assert( dest[ index ].format == format );
644 const Image& src = srcImages[ index ];
657 if ( compress & TEX_COMPRESS_PARALLEL )
686 _Use_decl_annotations_
692 if ( format == DXGI_FORMAT_UNKNOWN )
696 if ( format == DXGI_FORMAT_UNKNOWN )
708 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
731 _Use_decl_annotations_
735 if ( !cImages || !nimages )
741 if ( format == DXGI_FORMAT_UNKNOWN )
745 if ( format == DXGI_FORMAT_UNKNOWN )
757 HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
781 for(
size_t index=0; index < nimages; ++index )
783 assert( dest[ index ].format == format );
785 const Image& src = cImages[ index ];
_Use_decl_annotations_ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
static HRESULT _CompressBC(_In_ const Image &image, _In_ const Image &result, _In_ DWORD bcflags, _In_ DWORD srgb, _In_ float alphaRef)
const Image * GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const
void D3DXEncodeBC5U(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
void D3DXDecodeBC6HS(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
bool _IsAlphaAllOpaqueBC(_In_ const Image &cImage)
void(* BC_DECODE)(XMVECTOR *pColor, const uint8_t *pBC)
static DWORD _GetBCFlags(_In_ DWORD compress)
bool IsPlanar(_In_ DXGI_FORMAT fmt)
_Use_decl_annotations_ void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
void D3DXEncodeBC4U(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float threshold
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
HRESULT Initialize(_In_ const TexMetadata &mdata, _In_ DWORD flags=CP_FLAGS_NONE)
void D3DXEncodeBC4S(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
void D3DXDecodeBC4S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC)
HRESULT Initialize2D(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags=CP_FLAGS_NONE)
void D3DXEncodeBC6HU(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
_Use_decl_annotations_ bool _LoadScanline(XMVECTOR *pDestination, size_t count, LPCVOID pSource, size_t size, DXGI_FORMAT format)
void D3DXDecodeBC4U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC)
void D3DXDecodeBC6HU(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
static DXGI_FORMAT _DefaultDecompress(_In_ DXGI_FORMAT format)
bool IsCompressed(_In_ DXGI_FORMAT fmt)
size_t GetImageCount() const
static DWORD _GetSRGBFlags(_In_ DWORD compress)
_In_ size_t _In_ const TexMetadata & metadata
_Use_decl_annotations_ void _ConvertScanline(XMVECTOR *pBuffer, size_t count, DXGI_FORMAT outFormat, DXGI_FORMAT inFormat, DWORD flags)
void D3DXDecodeBC7(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
void D3DXEncodeBC6HS(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
bool IsValid(_In_ DXGI_FORMAT fmt)
void D3DXDecodeBC5U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
bool IsPalettized(_In_ DXGI_FORMAT fmt)
HRESULT Decompress(_In_ const Image &cImage, _In_ DXGI_FORMAT format, _Out_ ScratchImage &image)
_Use_decl_annotations_ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD flags)
bool IsTypeless(_In_ DXGI_FORMAT fmt, _In_ bool partialTypeless=true)
static bool _DetermineEncoderSettings(_In_ DXGI_FORMAT format, _Out_ BC_ENCODE &pfEncode, _Out_ size_t &blocksize, _Out_ DWORD &cflags)
static HRESULT _DecompressBC(_In_ const Image &cImage, _In_ const Image &result)
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
void D3DXDecodeBC5S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
void(* BC_ENCODE)(uint8_t *pDXT, const XMVECTOR *pColor, DWORD flags)
_Use_decl_annotations_ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
void D3DXEncodeBC5S(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
const Image * GetImages() const
size_t BitsPerPixel(_In_ DXGI_FORMAT fmt)
_Use_decl_annotations_ void D3DXDecodeBC1(XMVECTOR *pColor, const uint8_t *pBC)
HRESULT Compress(_In_ const Image &srcImage, _In_ DXGI_FORMAT format, _In_ DWORD compress, _In_ float alphaRef, _Out_ ScratchImage &cImage)
void D3DXEncodeBC7(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
_Use_decl_annotations_ bool _StoreScanline(LPVOID pDestination, size_t size, DXGI_FORMAT format, const XMVECTOR *pSource, size_t count, float threshold)
_Use_decl_annotations_ void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)