1
0
mirror of https://github.com/microsoft/DirectXTex synced 2025-01-03 23:11:05 +00:00

DirectXTex: Added DDS_FLAGS_EXPAND_LUMINANCE support

This commit is contained in:
walbourn_cp 2013-06-10 15:14:55 -07:00
parent 0a6e75fe5a
commit ae8a8cfa9a
2 changed files with 104 additions and 2 deletions

View File

@ -158,6 +158,9 @@ namespace DirectX
DDS_FLAGS_NO_16BPP = 0x10,
// Conversions avoid use of 565, 5551, and 4444 formats and instead expand to 8888 to avoid use of optional WDDM 1.2 formats
DDS_FLAGS_EXPAND_LUMINANCE = 0x20,
// When loading legacy luminance formats expand replicating the color channels rather than leaving them packed (L8, L16, A8L8)
DDS_FLAGS_FORCE_DX10_EXT = 0x10000,
// Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files)

View File

@ -40,6 +40,9 @@ enum CONVERSION_FLAGS
CONV_FLAGS_A8P8 = 0x800, // Has an 8-bit palette with an alpha channel
CONV_FLAGS_DX10 = 0x10000, // Has the 'DX10' extension header
CONV_FLAGS_PMALPHA = 0x20000, // Contains premultiplied alpha data
CONV_FLAGS_L8 = 0x40000, // Source is a 8 luminance format
CONV_FLAGS_L16 = 0x80000, // Source is a 16 luminance format
CONV_FLAGS_A8L8 = 0x100000, // Source is a 8:8 luminance format
};
struct LegacyDDS
@ -361,6 +364,28 @@ static HRESULT _DecodeDDSHeader( _In_reads_bytes_(size) LPCVOID pSource, size_t
if ( convFlags & CONV_FLAGS_PMALPHA )
metadata.miscFlags2 |= TEX_ALPHA_MODE_PREMULTIPLIED;
// Special flag for handling LUMINANCE legacy formats
if ( flags & DDS_FLAGS_EXPAND_LUMINANCE )
{
switch ( metadata.format )
{
case DXGI_FORMAT_R8_UNORM:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
convFlags |= CONV_FLAGS_L8 | CONV_FLAGS_EXPAND;
break;
case DXGI_FORMAT_R8G8_UNORM:
metadata.format = DXGI_FORMAT_R8G8B8A8_UNORM;
convFlags |= CONV_FLAGS_A8L8 | CONV_FLAGS_EXPAND;
break;
case DXGI_FORMAT_R16_UNORM:
metadata.format = DXGI_FORMAT_R16G16B16A16_UNORM;
convFlags |= CONV_FLAGS_L16 | CONV_FLAGS_EXPAND;
break;
}
}
}
// Special flag for handling BGR DXGI 1.1 formats
@ -673,6 +698,9 @@ enum TEXP_LEGACY_FORMAT
TEXP_LEGACY_A8P8,
TEXP_LEGACY_A4L4,
TEXP_LEGACY_B4G4R4A4,
TEXP_LEGACY_L8,
TEXP_LEGACY_L16,
TEXP_LEGACY_A8L8
};
inline static TEXP_LEGACY_FORMAT _FindLegacyFormat( DWORD flags )
@ -695,6 +723,12 @@ inline static TEXP_LEGACY_FORMAT _FindLegacyFormat( DWORD flags )
else if ( flags & CONV_FLAGS_4444 )
lformat = TEXP_LEGACY_B4G4R4A4;
#endif
else if ( flags & CONV_FLAGS_L8 )
lformat = TEXP_LEGACY_L8;
else if ( flags & CONV_FLAGS_L16 )
lformat = TEXP_LEGACY_L16;
else if ( flags & CONV_FLAGS_A8L8 )
lformat = TEXP_LEGACY_A8L8;
return lformat;
}
@ -904,6 +938,71 @@ static bool _LegacyExpandScanline( _Out_writes_bytes_(outSize) LPVOID pDestinati
}
return true;
#endif
case TEXP_LEGACY_L8:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
{
const uint8_t * __restrict sPtr = reinterpret_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); ++icount, ocount += 4 )
{
uint32_t t1 = *(sPtr++);
uint32_t t2 = (t1 << 8);
uint32_t t3 = (t1 << 16);
*(dPtr++) = t1 | t2 | t3 | 0xff000000;
}
}
return true;
case TEXP_LEGACY_L16:
if (outFormat != DXGI_FORMAT_R16G16B16A16_UNORM)
return false;
// D3DFMT_L16 -> DXGI_FORMAT_R16G16B16A16_UNORM
{
const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint64_t * __restrict dPtr = reinterpret_cast<uint64_t*>(pDestination);
for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 8 )
{
uint16_t t = *(sPtr++);
uint64_t t1 = t;
uint64_t t2 = (t1 << 16);
uint64_t t3 = (t1 << 32);
*(dPtr++) = t1 | t2 | t3 | 0xffff000000000000;
}
}
return true;
case TEXP_LEGACY_A8L8:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_A8L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
{
const uint16_t* __restrict sPtr = reinterpret_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = reinterpret_cast<uint32_t*>(pDestination);
for( size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < outSize)); icount += 2, ocount += 4 )
{
uint16_t t = *(sPtr++);
uint32_t t1 = (t & 0xff);
uint32_t t2 = (t1 << 8);
uint32_t t3 = (t1 << 16);
uint32_t ta = ( flags & TEXP_SCANLINE_SETALPHA ) ? 0xff000000 : ((t & 0xff00) << 16);
*(dPtr++) = t1 | t2 | t3 | ta;
}
}
return true;
}
return false;
@ -926,9 +1025,9 @@ static HRESULT _CopyImage( _In_reads_bytes_(size) const void* pPixels, _In_ size
{
if ( convFlags & CONV_FLAGS_888 )
cpFlags |= CP_FLAGS_24BPP;
else if ( convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 ) )
else if ( convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 | CONV_FLAGS_L16 | CONV_FLAGS_A8L8) )
cpFlags |= CP_FLAGS_16BPP;
else if ( convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8) )
else if ( convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8 | CONV_FLAGS_L8) )
cpFlags |= CP_FLAGS_8BPP;
}