in DirectXTex/DirectXTexDDS.cpp [921:1224]
bool LegacyExpandScanline(
_Out_writes_bytes_(outSize) void* pDestination,
size_t outSize,
_In_ DXGI_FORMAT outFormat,
_In_reads_bytes_(inSize) const void* pSource,
size_t inSize,
_In_ TEXP_LEGACY_FORMAT inFormat,
_In_reads_opt_(256) const uint32_t* pal8,
_In_ uint32_t tflags) noexcept
{
assert(pDestination && outSize > 0);
assert(pSource && inSize > 0);
assert(IsValid(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat));
switch (inFormat)
{
case TEXP_LEGACY_R8G8B8:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_R8G8B8 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 3 && outSize >= 4)
{
const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < (inSize - 2)) && (ocount < (outSize - 3))); icount += 3, ocount += 4)
{
// 24bpp Direct3D 9 files are actually BGR, so need to swizzle as well
uint32_t t1 = uint32_t(*(sPtr) << 16);
uint32_t t2 = uint32_t(*(sPtr + 1) << 8);
uint32_t t3 = uint32_t(*(sPtr + 2));
*(dPtr++) = t1 | t2 | t3 | 0xff000000;
sPtr += 3;
}
return true;
}
return false;
case TEXP_LEGACY_R3G3B2:
switch (outFormat)
{
case DXGI_FORMAT_R8G8B8A8_UNORM:
// D3DFMT_R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 1 && outSize >= 4)
{
const uint8_t* __restrict sPtr = static_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
{
uint8_t t = *(sPtr++);
uint32_t t1 = uint32_t((t & 0xe0) | ((t & 0xe0) >> 3) | ((t & 0xc0) >> 6));
uint32_t t2 = uint32_t(((t & 0x1c) << 11) | ((t & 0x1c) << 8) | ((t & 0x18) << 5));
uint32_t t3 = uint32_t(((t & 0x03) << 22) | ((t & 0x03) << 20) | ((t & 0x03) << 18) | ((t & 0x03) << 16));
*(dPtr++) = t1 | t2 | t3 | 0xff000000;
}
return true;
}
return false;
case DXGI_FORMAT_B5G6R5_UNORM:
// D3DFMT_R3G3B2 -> DXGI_FORMAT_B5G6R5_UNORM
if (inSize >= 1 && outSize >= 2)
{
const uint8_t* __restrict sPtr = static_cast<const uint8_t*>(pSource);
uint16_t * __restrict dPtr = static_cast<uint16_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2)
{
unsigned t = *(sPtr++);
unsigned t1 = ((t & 0xe0u) << 8) | ((t & 0xc0u) << 5);
unsigned t2 = ((t & 0x1cu) << 6) | ((t & 0x1cu) << 3);
unsigned t3 = ((t & 0x03u) << 3) | ((t & 0x03u) << 1) | ((t & 0x02) >> 1);
*(dPtr++) = static_cast<uint16_t>(t1 | t2 | t3);
}
return true;
}
return false;
default:
return false;
}
case TEXP_LEGACY_A8R3G3B2:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_A8R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 2 && outSize >= 4)
{
const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
{
uint16_t t = *(sPtr++);
uint32_t t1 = uint32_t((t & 0x00e0) | ((t & 0x00e0) >> 3) | ((t & 0x00c0) >> 6));
uint32_t t2 = uint32_t(((t & 0x001c) << 11) | ((t & 0x001c) << 8) | ((t & 0x0018) << 5));
uint32_t t3 = uint32_t(((t & 0x0003) << 22) | ((t & 0x0003) << 20) | ((t & 0x0003) << 18) | ((t & 0x0003) << 16));
uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t((t & 0xff00) << 16);
*(dPtr++) = t1 | t2 | t3 | ta;
}
return true;
}
return false;
case TEXP_LEGACY_P8:
if ((outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8)
return false;
// D3DFMT_P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 1 && outSize >= 4)
{
const uint8_t* __restrict sPtr = static_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
{
uint8_t t = *(sPtr++);
*(dPtr++) = pal8[t];
}
return true;
}
return false;
case TEXP_LEGACY_A8P8:
if ((outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8)
return false;
// D3DFMT_A8P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 2 && outSize >= 4)
{
const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
{
uint16_t t = *(sPtr++);
uint32_t t1 = pal8[t & 0xff];
uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t((t & 0xff00) << 16);
*(dPtr++) = t1 | ta;
}
return true;
}
return false;
case TEXP_LEGACY_A4L4:
switch (outFormat)
{
case DXGI_FORMAT_B4G4R4A4_UNORM:
// D3DFMT_A4L4 -> DXGI_FORMAT_B4G4R4A4_UNORM
if (inSize >= 1 && outSize >= 2)
{
const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
uint16_t * __restrict dPtr = static_cast<uint16_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2)
{
unsigned t = *(sPtr++);
unsigned t1 = (t & 0x0fu);
unsigned ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xf000u : ((t & 0xf0u) << 8);
*(dPtr++) = static_cast<uint16_t>(t1 | (t1 << 4) | (t1 << 8) | ta);
}
return true;
}
return false;
case DXGI_FORMAT_R8G8B8A8_UNORM:
// D3DFMT_A4L4 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 1 && outSize >= 4)
{
const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
{
uint8_t t = *(sPtr++);
uint32_t t1 = uint32_t(((t & 0x0f) << 4) | (t & 0x0f));
uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t(((t & 0xf0) << 24) | ((t & 0xf0) << 20));
*(dPtr++) = t1 | (t1 << 8) | (t1 << 16) | ta;
}
return true;
}
return false;
default:
return false;
}
case TEXP_LEGACY_B4G4R4A4:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_A4R4G4B4 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 2 && outSize >= 4)
{
const uint16_t * __restrict sPtr = static_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
{
uint32_t t = *(sPtr++);
uint32_t t1 = uint32_t((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8);
uint32_t t2 = uint32_t((t & 0x00f0) << 8) | ((t & 0x00f0) << 4);
uint32_t t3 = uint32_t((t & 0x000f) << 20) | ((t & 0x000f) << 16);
uint32_t ta = uint32_t((tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : (((t & 0xf000) << 16) | ((t & 0xf000) << 12)));
*(dPtr++) = t1 | t2 | t3 | ta;
}
return true;
}
return false;
case TEXP_LEGACY_L8:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 1 && outSize >= 4)
{
const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
{
uint32_t t1 = *(sPtr++);
uint32_t t2 = (t1 << 8);
uint32_t t3 = (t1 << 16);
*(dPtr++) = t1 | t2 | t3 | 0xff000000;
}
return true;
}
return false;
case TEXP_LEGACY_L16:
if (outFormat != DXGI_FORMAT_R16G16B16A16_UNORM)
return false;
// D3DFMT_L16 -> DXGI_FORMAT_R16G16B16A16_UNORM
if (inSize >= 2 && outSize >= 8)
{
const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
uint64_t * __restrict dPtr = static_cast<uint64_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 7))); 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;
}
return false;
case TEXP_LEGACY_A8L8:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
// D3DFMT_A8L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
if (inSize >= 2 && outSize >= 4)
{
const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);
for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
{
uint16_t t = *(sPtr++);
uint32_t t1 = uint32_t(t & 0xff);
uint32_t t2 = uint32_t(t1 << 8);
uint32_t t3 = uint32_t(t1 << 16);
uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t((t & 0xff00) << 16);
*(dPtr++) = t1 | t2 | t3 | ta;
}
return true;
}
return false;
default:
return false;
}
}