From 7c63695e1d48ffd95ef984277143832a5e2ef55f Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 6 Aug 2024 23:33:17 -0700 Subject: [PATCH 1/7] DDS codec updated to convert legacy X8L8V8U8/LVU655/UVW10 formats --- DirectXTex/DirectXTexDDS.cpp | 114 +++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 13 deletions(-) diff --git a/DirectXTex/DirectXTexDDS.cpp b/DirectXTex/DirectXTexDDS.cpp index 0daf9423..f2a5e59b 100644 --- a/DirectXTex/DirectXTexDDS.cpp +++ b/DirectXTex/DirectXTexDDS.cpp @@ -46,6 +46,9 @@ 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_L8U8V8 = 0x400000, // Source is a X:8:8:8 bumpluminance format + CONV_FLAGS_WUV10 = 0x800000, // Source is a 2:10:10:10 bump format }; struct LegacyDDS @@ -157,6 +160,11 @@ namespace { DXGI_FORMAT_R8G8_SNORM, CONV_FLAGS_NONE, DDSPF_V8U8 }, // D3DFMT_V8U8 { 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 + | 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 }; // Note that many common DDS reader/writers (including D3DX) swap the @@ -248,12 +256,24 @@ namespace } else if (entry->ddpf.flags & DDS_BUMPDUDV) { - if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount - && ddpf.RBitMask == entry->ddpf.RBitMask - && ddpf.GBitMask == entry->ddpf.GBitMask - && ddpf.BBitMask == entry->ddpf.BBitMask - && ddpf.ABitMask == entry->ddpf.ABitMask) - break; + if (entry->ddpf.flags & DDS_ALPHAPIXELS) + { + // BUMPDUDVA + if (ddpf.RBitMask == entry->ddpf.RBitMask + && ddpf.GBitMask == entry->ddpf.GBitMask + && ddpf.BBitMask == entry->ddpf.BBitMask + && ddpf.ABitMask == entry->ddpf.ABitMask) + break; + } + else + { + // BUMPDUDV + if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount + && ddpf.RBitMask == entry->ddpf.RBitMask + && ddpf.GBitMask == entry->ddpf.GBitMask + && ddpf.BBitMask == entry->ddpf.BBitMask) + break; + } } else if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount) { @@ -996,7 +1016,10 @@ namespace TEXP_LEGACY_B4G4R4A4, TEXP_LEGACY_L8, TEXP_LEGACY_L16, - TEXP_LEGACY_A8L8 + TEXP_LEGACY_A8L8, + TEXP_LEGACY_L6U5V5, + TEXP_LEGACY_X8L8V8U8, + TEXP_LEGACY_A2W10V10U10 }; constexpr TEXP_LEGACY_FORMAT FindLegacyFormat(uint32_t flags) noexcept @@ -1023,6 +1046,12 @@ 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_L8U8V8) + lformat = TEXP_LEGACY_X8L8V8U8; + else if (flags & CONV_FLAGS_WUV10) + lformat = TEXP_LEGACY_A2W10V10U10; return lformat; } @@ -1328,11 +1357,50 @@ namespace } return false; + case TEXP_LEGACY_L6U5V5: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // TODO - converts unsigned 6-bit/signed 5-bit/signed 5-bit bump luminance to 8:8:8:8 unsigned + return false; + default: return false; } } + _Success_(return) + bool LegacyConvertScanline( + _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) noexcept + { + assert(pDestination && outSize > 0); + assert(pSource && inSize > 0); + + switch (inFormat) + { + case TEXP_LEGACY_X8L8V8U8: + if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) + return false; + + // TODO - Converts 8-bit unsigned / 8-bit signed / 8-bit signed to 8:8:8:8 unsigned + return false; + + case TEXP_LEGACY_A2W10V10U10: + if (outFormat != DXGI_FORMAT_R10G10B10A2_UNORM) + return false; + + // TODO - Converts 2-bit unsigned / 10-bit signed / 10-bit signed / 10-bit signed to 2:10:10:10 unsigned + return false; + + default: + return false; + } + } //------------------------------------------------------------------------------------- // Converts or copies image data from pPixels into scratch image data @@ -1356,7 +1424,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)) + 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)) cpFlags |= CP_FLAGS_16BPP; else if (convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8 | CONV_FLAGS_L8)) cpFlags |= CP_FLAGS_8BPP; @@ -1502,13 +1570,18 @@ namespace } else if (convFlags & CONV_FLAGS_SWIZZLE) { - SwizzleScanline(pDest, dpitch, pSrc, spitch, - metadata.format, tflags); + SwizzleScanline(pDest, dpitch, pSrc, spitch, metadata.format, tflags); + } + else if (convFlags & (CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10)) + { + const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat(convFlags); + if (!LegacyConvertScanline(pDest, dpitch, metadata.format, + pSrc, spitch, lformat)) + return E_FAIL; } else { - CopyScanline(pDest, dpitch, pSrc, spitch, - metadata.format, tflags); + CopyScanline(pDest, dpitch, pSrc, spitch, metadata.format, tflags); } pSrc += spitch; @@ -1605,6 +1678,13 @@ namespace { SwizzleScanline(pDest, dpitch, pSrc, spitch, metadata.format, tflags); } + else if (convFlags & (CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10)) + { + const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat(convFlags); + if (!LegacyConvertScanline(pDest, dpitch, metadata.format, + pSrc, spitch, lformat)) + return E_FAIL; + } else { CopyScanline(pDest, dpitch, pSrc, spitch, metadata.format, tflags); @@ -1662,6 +1742,14 @@ namespace { SwizzleScanline(pPixels, rowPitch, pPixels, rowPitch, metadata.format, tflags); } + 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)) + { + return E_UNEXPECTED; + } + } else { CopyScanline(pPixels, rowPitch, pPixels, rowPitch, metadata.format, tflags); @@ -2133,7 +2221,7 @@ HRESULT DirectX::LoadFromDDSFileEx( } #endif - if (convFlags & (CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA)) + if (convFlags & (CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA | CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10)) { // Swizzle/copy image in place hr = CopyImageInPlace(convFlags, image); From cb049e997bdd793fca76bf0dae24ec9385deac89 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Thu, 15 Aug 2024 15:07:20 -0700 Subject: [PATCH 2/7] Added TOOD --- DirectXTex/DirectXTexDDS.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/DirectXTex/DirectXTexDDS.cpp b/DirectXTex/DirectXTexDDS.cpp index f2a5e59b..726f59c9 100644 --- a/DirectXTex/DirectXTexDDS.cpp +++ b/DirectXTex/DirectXTexDDS.cpp @@ -1381,6 +1381,12 @@ namespace 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: From 458b659f8c8ac1ae1f1376c831c147d55838d793 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Tue, 20 Aug 2024 11:44:33 -0700 Subject: [PATCH 3/7] More work on dds --- DirectXTex/DirectXTexDDS.cpp | 74 ++++++++++++------------------------ 1 file changed, 24 insertions(+), 50 deletions(-) diff --git a/DirectXTex/DirectXTexDDS.cpp b/DirectXTex/DirectXTexDDS.cpp index 726f59c9..2b22266d 100644 --- a/DirectXTex/DirectXTexDDS.cpp +++ b/DirectXTex/DirectXTexDDS.cpp @@ -144,7 +144,7 @@ namespace { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND | CONV_FLAGS_PAL8 - | CONV_FLAGS_A8P8, { sizeof(DDS_PIXELFORMAT), DDS_PAL8A, 0, 16, 0, 0, 0, 0 } }, // D3DFMT_A8P8 + | CONV_FLAGS_A8P8, { sizeof(DDS_PIXELFORMAT), DDS_PAL8A, 0, 16, 0, 0, 0, 0xff00 } }, // D3DFMT_A8P8 { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND | CONV_FLAGS_PAL8, { sizeof(DDS_PIXELFORMAT), DDS_PAL8, 0, 8, 0, 0, 0, 0 } }, // D3DFMT_P8 @@ -174,8 +174,6 @@ namespace // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly // We do not support the following legacy Direct3D 9 formats: - // BumpDuDv D3DFMT_A2W10V10U10 - // BumpLuminance D3DFMT_L6V5U5, D3DFMT_X8L8V8U8 // FourCC 117 D3DFMT_CxV8U8 // ZBuffer D3DFMT_D16_LOCKABLE // FourCC 82 D3DFMT_D32F_LOCKABLE @@ -223,17 +221,16 @@ namespace if (ddpf.fourCC == entry->ddpf.fourCC) break; } - else if (ddpfFlags == entry->ddpf.flags) + else if ((ddpfFlags == entry->ddpf.flags) && (ddpf.RGBBitCount == entry->ddpf.RGBBitCount)) { if (entry->ddpf.flags & DDS_PAL8) { - if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount) - break; + // PAL8 / PAL8A + break; } else if (entry->ddpf.flags & DDS_ALPHA) { - if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount - && ddpf.ABitMask == entry->ddpf.ABitMask) + if (ddpf.ABitMask == entry->ddpf.ABitMask) break; } else if (entry->ddpf.flags & DDS_LUMINANCE) @@ -241,59 +238,33 @@ namespace if (entry->ddpf.flags & DDS_ALPHAPIXELS) { // LUMINANCEA - if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount - && ddpf.RBitMask == entry->ddpf.RBitMask + if (ddpf.RBitMask == entry->ddpf.RBitMask && ddpf.ABitMask == entry->ddpf.ABitMask) break; } else { // LUMINANCE - if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount - && ddpf.RBitMask == entry->ddpf.RBitMask) + if (ddpf.RBitMask == entry->ddpf.RBitMask) break; } } - else if (entry->ddpf.flags & DDS_BUMPDUDV) + else if (entry->ddpf.flags & DDS_ALPHAPIXELS) { - if (entry->ddpf.flags & DDS_ALPHAPIXELS) - { - // BUMPDUDVA - if (ddpf.RBitMask == entry->ddpf.RBitMask - && ddpf.GBitMask == entry->ddpf.GBitMask - && ddpf.BBitMask == entry->ddpf.BBitMask - && ddpf.ABitMask == entry->ddpf.ABitMask) - break; - } - else - { - // BUMPDUDV - if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount - && ddpf.RBitMask == entry->ddpf.RBitMask - && ddpf.GBitMask == entry->ddpf.GBitMask - && ddpf.BBitMask == entry->ddpf.BBitMask) - break; - } + // RGBA / BUMPDUDVA + if (ddpf.RBitMask == entry->ddpf.RBitMask + && ddpf.GBitMask == entry->ddpf.GBitMask + && ddpf.BBitMask == entry->ddpf.BBitMask + && ddpf.ABitMask == entry->ddpf.ABitMask) + break; } - else if (ddpf.RGBBitCount == entry->ddpf.RGBBitCount) + else { - if (entry->ddpf.flags & DDS_ALPHAPIXELS) - { - // RGBA - if (ddpf.RBitMask == entry->ddpf.RBitMask - && ddpf.GBitMask == entry->ddpf.GBitMask - && ddpf.BBitMask == entry->ddpf.BBitMask - && ddpf.ABitMask == entry->ddpf.ABitMask) - break; - } - else - { - // RGB - if (ddpf.RBitMask == entry->ddpf.RBitMask - && ddpf.GBitMask == entry->ddpf.GBitMask - && ddpf.BBitMask == entry->ddpf.BBitMask) - break; - } + // RGB / BUMPDUDV + if (ddpf.RBitMask == entry->ddpf.RBitMask + && ddpf.GBitMask == entry->ddpf.GBitMask + && ddpf.BBitMask == entry->ddpf.BBitMask) + break; } } } @@ -1361,6 +1332,7 @@ namespace 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 return false; @@ -1381,7 +1353,7 @@ namespace assert(pDestination && outSize > 0); assert(pSource && inSize > 0); - // TODO - + // TODO - UNREFERENCED_PARAMETER(pDestination); UNREFERENCED_PARAMETER(outSize); UNREFERENCED_PARAMETER(pSource); @@ -1393,6 +1365,7 @@ namespace 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 return false; @@ -1400,6 +1373,7 @@ namespace 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 return false; From f22b6b3ffcc816f13e56607293845ffbd695d1e9 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 28 Aug 2024 12:08:50 -0700 Subject: [PATCH 4/7] Minor update for ScreenGrab9 to match DDS.h --- ScreenGrab/ScreenGrab9.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ScreenGrab/ScreenGrab9.cpp b/ScreenGrab/ScreenGrab9.cpp index 43077c19..38c4a579 100644 --- a/ScreenGrab/ScreenGrab9.cpp +++ b/ScreenGrab/ScreenGrab9.cpp @@ -85,8 +85,9 @@ namespace #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE #define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS #define DDS_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV #define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE +#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV +#define DDS_BUMPDUDVA 0x00080001 // DDPF_BUMPDUDV | DDPF_ALPHAPIXELS #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT @@ -206,7 +207,7 @@ namespace { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0 }; const DDS_PIXELFORMAT DDSPF_A2W10V10U10 = - { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }; + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDVA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }; const DDS_PIXELFORMAT DDSPF_L6V5U5 = { sizeof(DDS_PIXELFORMAT), DDS_BUMPLUMINANCE, 0, 16, 0x001f, 0x03e0, 0xfc00, 0 }; From 8ac109bbb6c32194eeeb310dd347f35e924401ee Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 28 Aug 2024 15:46:01 -0700 Subject: [PATCH 5/7] Revert "Minor update for ScreenGrab9 to match DDS.h" This reverts commit f22b6b3ffcc816f13e56607293845ffbd695d1e9. --- ScreenGrab/ScreenGrab9.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ScreenGrab/ScreenGrab9.cpp b/ScreenGrab/ScreenGrab9.cpp index 38c4a579..43077c19 100644 --- a/ScreenGrab/ScreenGrab9.cpp +++ b/ScreenGrab/ScreenGrab9.cpp @@ -85,9 +85,8 @@ namespace #define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE #define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS #define DDS_ALPHA 0x00000002 // DDPF_ALPHA -#define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE #define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV -#define DDS_BUMPDUDVA 0x00080001 // DDPF_BUMPDUDV | DDPF_ALPHAPIXELS +#define DDS_BUMPLUMINANCE 0x00040000 // DDPF_BUMPLUMINANCE #define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT #define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT @@ -207,7 +206,7 @@ namespace { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0 }; const DDS_PIXELFORMAT DDSPF_A2W10V10U10 = - { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDVA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }; + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }; const DDS_PIXELFORMAT DDSPF_L6V5U5 = { sizeof(DDS_PIXELFORMAT), DDS_BUMPLUMINANCE, 0, 16, 0x001f, 0x03e0, 0xfc00, 0 }; From 3b366ed8b7a7a160368119aaad99f91f4f939150 Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 28 Aug 2024 18:57:03 -0700 Subject: [PATCH 6/7] Implement DDS loading for mixed channel formas --- DirectXTex/DirectXTexDDS.cpp | 130 ++++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 25 deletions(-) diff --git a/DirectXTex/DirectXTexDDS.cpp b/DirectXTex/DirectXTexDDS.cpp index 2b22266d..fd1950f3 100644 --- a/DirectXTex/DirectXTexDDS.cpp +++ b/DirectXTex/DirectXTexDDS.cpp @@ -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 }; @@ -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 @@ -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 @@ -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) @@ -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 }; @@ -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) @@ -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(pSource); + uint32_t * __restrict dPtr = static_cast(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: @@ -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(pSource); + auto dPtr = static_cast(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(pSource); + auto dPtr = static_cast(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: @@ -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; @@ -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 @@ -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 @@ -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; } From caddf0f683ae4462e9e0d8c2ad7e08d2178e46da Mon Sep 17 00:00:00 2001 From: Chuck Walbourn Date: Wed, 28 Aug 2024 22:11:18 -0700 Subject: [PATCH 7/7] Minor comment update --- DirectXTex/DirectXTexDDS.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DirectXTex/DirectXTexDDS.cpp b/DirectXTex/DirectXTexDDS.cpp index fd1950f3..de5deb08 100644 --- a/DirectXTex/DirectXTexDDS.cpp +++ b/DirectXTex/DirectXTexDDS.cpp @@ -174,13 +174,14 @@ namespace // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly // We do not support the following legacy Direct3D 9 formats: - // FourCC 117 D3DFMT_CxV8U8 - // ZBuffer D3DFMT_D16_LOCKABLE + // D3DFMT_D16_LOCKABLE (DDPF_ZBUFFER: 0x00000400) // FourCC 82 D3DFMT_D32F_LOCKABLE + // FourCC 117 D3DFMT_CxV8U8 // We do not support the following known FourCC codes: // FourCC CTX1 (Xbox 360 only) // FourCC EAR, EARG, ET2, ET2A (Ericsson Texture Compression) + // FourCC MET1 (a.k.a. D3DFMT_MULTI2_ARGB8; rarely supported by any hardware) DXGI_FORMAT GetDXGIFormat(const DDS_HEADER& hdr, const DDS_PIXELFORMAT& ddpf, DDS_FLAGS flags,