render parity unit K: 40250 DDS mip levels

DXT DDS textures upload the file's own mip levels like 40250
CGraphicImageTexture::CreateDDSTexture (max(1, dwMipMapCount), level i read
at sum(dwLinearSize>>2k), Copy of dwLinearSize>>2i bytes) instead of a
regenerated chain. Non-DDS images keep the D3DX_DEFAULT full chain and mem:
textures get one level. The invented is_ui_tex no-mip rule (icon/, ui/,
locale/, <=128px) is deleted. dxt_decode_test is registered in ctest with
mip-level cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-28 14:29:30 +09:00
co-authored by Claude Opus 5.5
parent dda885a17a
commit d2356d59c3
7 changed files with 177 additions and 46 deletions
+19 -1
View File
@@ -47,5 +47,23 @@ int main() {
if (fourcc == 0x35545844) dxt[128] = 255;
pixel(decode(dxt), 0, 255, 0, 0, 255);
}
std::puts("PASS: dxt_decode_test (masked RGB, pitch, invalid headers, DXT1/3/5)");
{ // 40250 CreateDDSTexture levels: DDSD_MIPMAPCOUNT, level i at sum(linear >> 2k),
// Copy() takes linear >> 2i bytes (the 2x2 level gets 2 of its 8 block bytes).
auto mip = header(0, 0, 0, 0, 0, 32 + 8 + 2);
put(mip, 8, 0x1007 | 0x20000 | 0x80000); put(mip, 12, 8); put(mip, 16, 8);
put(mip, 20, 32); put(mip, 28, 3); put(mip, 80, 4); put(mip, 84, 0x31545844u);
for (int blk = 0; blk < 4; ++blk) put(mip, 128 + blk * 8, 0x000007e0); // level 0 green
put(mip, 160, 0x0000001f); // level 1 blue
mip[168] = 0x00; mip[169] = 0xf8; // level 2 red
auto im = decode(mip);
assert(im.w == 8 && im.h == 8 && im.file_mip_levels == 3 && im.mips.size() == 2);
pixel(im, 63, 0, 255, 0, 255);
assert(im.mips[0].size() == 4 * 4 * 4 && im.mips[0][2] == 255 && im.mips[0][0] == 0);
assert(im.mips[1].size() == 2 * 2 * 4 && im.mips[1][0] == 255 && im.mips[1][1] == 0);
put(mip, 8, 0x1007 | 0x80000); // no DDSD_MIPMAPCOUNT -> only level 0 is filled
im = decode(mip);
assert(im.file_mip_levels == 1 && im.mips.empty());
assert(decode(a1555).file_mip_levels == 0); // non-DXT -> D3DX full-chain path
}
std::puts("PASS: dxt_decode_test (masked RGB, pitch, invalid headers, DXT1/3/5, mip levels)");
}