Skip to content

Commit

Permalink
Implement DDS loading for mixed channel formas
Browse files Browse the repository at this point in the history
  • Loading branch information
walbourn committed Aug 29, 2024
1 parent 8ac109b commit 3b366ed
Showing 1 changed file with 105 additions and 25 deletions.
130 changes: 105 additions & 25 deletions DirectXTex/DirectXTexDDS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace
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
CONV_FLAGS_L6U5V5 = 0x200000, // Source is a 6:5:5 bumpluminance format
CONV_FLAGS_L6V5U5 = 0x200000, // Source is a 6:5:5 bumpluminance format
CONV_FLAGS_L8U8V8 = 0x400000, // Source is a X:8:8:8 bumpluminance format
CONV_FLAGS_WUV10 = 0x800000, // Source is a 2:10:10:10 bump format
};
Expand Down Expand Up @@ -161,7 +161,7 @@ namespace
{ DXGI_FORMAT_R8G8B8A8_SNORM, CONV_FLAGS_NONE, DDSPF_Q8W8V8U8 }, // D3DFMT_Q8W8V8U8
{ DXGI_FORMAT_R16G16_SNORM, CONV_FLAGS_NONE, DDSPF_V16U16 }, // D3DFMT_V16U16

{ DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_L6U5V5
{ DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_L6V5U5
| CONV_FLAGS_EXPAND, DDSPF_L6V5U5 }, // D3DFMT_L6V5U5
{ DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_L8U8V8, DDSPF_X8L8V8U8 }, // D3DFMT_X8L8V8U8
{ DXGI_FORMAT_R10G10B10A2_UNORM, CONV_FLAGS_WUV10, DDSPF_A2W10V10U10 }, // D3DFMT_A2W10V10U10
Expand Down Expand Up @@ -249,9 +249,28 @@ namespace
break;
}
}
else if (entry->ddpf.flags & DDS_BUMPDUDV)
{
if (entry->ddpf.flags & DDS_ALPHAPIXELS)
{
// BUMPDUDVA
if (ddpf.RBitMask == entry->ddpf.RBitMask
&& ddpf.ABitMask == entry->ddpf.ABitMask)
{
flags &= ~DDS_FLAGS_NO_R10B10G10A2_FIXUP;
break;
}
}
else
{
// BUMPDUDV
if (ddpf.RBitMask == entry->ddpf.RBitMask)
break;
}
}
else if (entry->ddpf.flags & DDS_ALPHAPIXELS)
{
// RGBA / BUMPDUDVA
// RGBA
if (ddpf.RBitMask == entry->ddpf.RBitMask
&& ddpf.GBitMask == entry->ddpf.GBitMask
&& ddpf.BBitMask == entry->ddpf.BBitMask
Expand All @@ -260,7 +279,7 @@ namespace
}
else
{
// RGB / BUMPDUDV
// RGB
if (ddpf.RBitMask == entry->ddpf.RBitMask
&& ddpf.GBitMask == entry->ddpf.GBitMask
&& ddpf.BBitMask == entry->ddpf.BBitMask)
Expand Down Expand Up @@ -988,7 +1007,7 @@ namespace
TEXP_LEGACY_L8,
TEXP_LEGACY_L16,
TEXP_LEGACY_A8L8,
TEXP_LEGACY_L6U5V5,
TEXP_LEGACY_L6V5U5,
TEXP_LEGACY_X8L8V8U8,
TEXP_LEGACY_A2W10V10U10
};
Expand Down Expand Up @@ -1017,8 +1036,8 @@ namespace
lformat = TEXP_LEGACY_L16;
else if (flags & CONV_FLAGS_A8L8)
lformat = TEXP_LEGACY_A8L8;
else if (flags & CONV_FLAGS_L6U5V5)
lformat = TEXP_LEGACY_L6U5V5;
else if (flags & CONV_FLAGS_L6V5U5)
lformat = TEXP_LEGACY_L6V5U5;
else if (flags & CONV_FLAGS_L8U8V8)
lformat = TEXP_LEGACY_X8L8V8U8;
else if (flags & CONV_FLAGS_WUV10)
Expand Down Expand Up @@ -1328,12 +1347,34 @@ namespace
}
return false;

case TEXP_LEGACY_L6U5V5:
case TEXP_LEGACY_L6V5U5:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;

// D3DFMT_L6U5V5 -> DXGI_FORMAT_R8G8B8A8_UNORM
// TODO - converts unsigned 6-bit/signed 5-bit/signed 5-bit bump luminance to 8:8:8:8 unsigned
// D3DFMT_L6V5U5 -> DXGI_FORMAT_R8G8B8A8_UNORM (LUVA)
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)
{
const uint16_t t = *(sPtr++);

// Converts unsigned 6-bit/signed 5-bit/signed 5-bit bump luminance to 8:8:8:8 unsigned
uint32_t t1 = ((t & 0xFC00) >> 8) | ((t & 0xC000) >> 14);

constexpr int m = 1U << 4;
int8_t v = ((((t >> 5) & 0x1f) ^ m) - m) + 16;
int8_t u = (((t & 0x1f) ^ m) - m) + 16;

uint32_t t2 = u << 3 | u >> 2;
uint32_t t3 = v << 3 | v >> 2;

*(dPtr++) = t1 | (t2 << 8) | (t3 << 16) | 0xff000000;
}
return true;
}
return false;

default:
Expand All @@ -1348,33 +1389,72 @@ namespace
_In_ DXGI_FORMAT outFormat,
_In_reads_bytes_(inSize) const void* pSource,
size_t inSize,
_In_ TEXP_LEGACY_FORMAT inFormat) noexcept
_In_ TEXP_LEGACY_FORMAT inFormat,
uint32_t tflags) noexcept
{
assert(pDestination && outSize > 0);
assert(pSource && inSize > 0);

// TODO -
UNREFERENCED_PARAMETER(pDestination);
UNREFERENCED_PARAMETER(outSize);
UNREFERENCED_PARAMETER(pSource);
UNREFERENCED_PARAMETER(inSize);

switch (inFormat)
{
case TEXP_LEGACY_X8L8V8U8:
if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
return false;

// D3DFMT_X8L8V8U8 -> DXGI_FORMAT_R8G8B8A8_UNORM
// TODO - Converts 8-bit unsigned / 8-bit signed / 8-bit signed to 8:8:8:8 unsigned
// D3DFMT_X8L8V8U8 -> DXGI_FORMAT_R8G8B8A8_UNORM (LUVA)
if (inSize >= 4 && outSize >= 4)
{
auto sPtr = static_cast<const uint32_t*>(pSource);
auto dPtr = static_cast<uint32_t*>(pDestination);

for (size_t ocount = 0, icount = 0; ((icount < (inSize - 3)) && (ocount < (outSize - 3))); icount += 4, ocount += 4)
{
const uint32_t t = *(sPtr++);

// Converts 8-bit unsigned / 8-bit signed / 8-bit signed to 8:8:8:8 unsigned
uint32_t t1 = (t >> 16) & 0xff;
constexpr int m = 1U << 7;
uint32_t v = ((((t >> 8) & 0xff) ^ m) - m) + 128;
uint32_t u = (((t & 0xff) ^ m) - m) + 128;

uint32_t t2 = u << 8;
uint32_t t3 = v << 16;

*(dPtr++) = t1 | t2 | t3 | 0xff000000;
}
return true;
}
return false;

case TEXP_LEGACY_A2W10V10U10:
if (outFormat != DXGI_FORMAT_R10G10B10A2_UNORM)
return false;

// D3DFMT_A2W10V10U10 -> DXGI_FORMAT_R10G10B10A2_UNORM
// TODO - Converts 2-bit unsigned / 10-bit signed / 10-bit signed / 10-bit signed to 2:10:10:10 unsigned
// D3DFMT_A2W10V10U10 -> DXGI_FORMAT_R10G10B10A2_UNORM (UVWA)
if (inSize >= 4 && outSize >= 4)
{
auto sPtr = static_cast<const uint32_t*>(pSource);
auto dPtr = static_cast<uint32_t*>(pDestination);

for (size_t ocount = 0, icount = 0; ((icount < (inSize - 3)) && (ocount < (outSize - 3))); icount += 4, ocount += 4)
{
const uint32_t t = *(sPtr++);

// Converts 2-bit unsigned / 10-bit signed / 10-bit signed / 10-bit signed to 2:10:10:10 unsigned
constexpr int m = 1U << 9;
uint32_t w = ((((t >> 20) & 0x3ff) ^ m) - m) + 512;
uint32_t v = ((((t >> 10) & 0x3ff) ^ m) - m) + 512;
uint32_t u = (((t & 0x3ff) ^ m) - m) + 512;

uint32_t t1 = u;
uint32_t t2 = v << 10;
uint32_t t3 = w << 20;
uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xC0000000 : (t & 0xC0000000);

*(dPtr++) = t1 | t2 | t3 | ta;
}
return true;
}
return false;

default:
Expand Down Expand Up @@ -1404,7 +1484,7 @@ namespace
{
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 | CONV_FLAGS_L16 | CONV_FLAGS_A8L8 | CONV_FLAGS_L6U5V5))
else if (convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 | CONV_FLAGS_L16 | CONV_FLAGS_A8L8 | CONV_FLAGS_L6V5U5))
cpFlags |= CP_FLAGS_16BPP;
else if (convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8 | CONV_FLAGS_L8))
cpFlags |= CP_FLAGS_8BPP;
Expand Down Expand Up @@ -1556,7 +1636,7 @@ namespace
{
const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat(convFlags);
if (!LegacyConvertScanline(pDest, dpitch, metadata.format,
pSrc, spitch, lformat))
pSrc, spitch, lformat, tflags))
return E_FAIL;
}
else
Expand Down Expand Up @@ -1662,7 +1742,7 @@ namespace
{
const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat(convFlags);
if (!LegacyConvertScanline(pDest, dpitch, metadata.format,
pSrc, spitch, lformat))
pSrc, spitch, lformat, tflags))
return E_FAIL;
}
else
Expand Down Expand Up @@ -1725,7 +1805,7 @@ namespace
else if (convFlags & (CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10))
{
const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat(convFlags);
if (!LegacyConvertScanline(pPixels, rowPitch, metadata.format, pPixels, rowPitch, lformat))
if (!LegacyConvertScanline(pPixels, rowPitch, metadata.format, pPixels, rowPitch, lformat, tflags))
{
return E_UNEXPECTED;
}
Expand Down

0 comments on commit 3b366ed

Please sign in to comment.