badtails flag to enable loading of legacy DXTn DDS files with incomplete mipchain tails
This commit is contained in:
Родитель
04143d621c
Коммит
7275893dbe
|
@ -70,6 +70,7 @@ namespace DirectX
|
|||
CP_FLAGS_YMM = 0x4, // Assume pitch is 32-byte aligned instead of BYTE aligned
|
||||
CP_FLAGS_ZMM = 0x8, // Assume pitch is 64-byte aligned instead of BYTE aligned
|
||||
CP_FLAGS_PAGE4K = 0x200, // Assume pitch is 4096-byte aligned instead of BYTE aligned
|
||||
CP_FLAGS_BAD_DXTN_TAILS = 0x1000, // BC formats with malformed mipchain blocks smaller than 4x4
|
||||
CP_FLAGS_24BPP = 0x10000, // Override with a legacy 24 bits-per-pixel format size
|
||||
CP_FLAGS_16BPP = 0x20000, // Override with a legacy 16 bits-per-pixel format size
|
||||
CP_FLAGS_8BPP = 0x40000, // Override with a legacy 8 bits-per-pixel format size
|
||||
|
@ -164,6 +165,9 @@ namespace DirectX
|
|||
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_BAD_DXTN_TAILS = 0x40,
|
||||
// Some older DXTn DDS files incorrectly handle mipchain tails for blocks smaller than 4x4
|
||||
|
||||
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)
|
||||
|
||||
|
|
|
@ -1068,7 +1068,7 @@ namespace
|
|||
|
||||
if (pixelSize > size)
|
||||
{
|
||||
return E_FAIL;
|
||||
return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
|
||||
}
|
||||
|
||||
std::unique_ptr<Image[]> timages(new (std::nothrow) Image[nimages]);
|
||||
|
@ -1077,7 +1077,7 @@ namespace
|
|||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if (!_SetupImageArray((uint8_t*)pPixels, size, metadata, cpFlags, timages.get(), nimages))
|
||||
if (!_SetupImageArray((uint8_t*)pPixels, pixelSize, metadata, cpFlags, timages.get(), nimages))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
@ -1105,6 +1105,7 @@ namespace
|
|||
size_t index = 0;
|
||||
for (size_t item = 0; item < metadata.arraySize; ++item)
|
||||
{
|
||||
size_t lastgood = 0;
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level, ++index)
|
||||
{
|
||||
if (index >= nimages)
|
||||
|
@ -1128,6 +1129,19 @@ namespace
|
|||
{
|
||||
size_t csize = std::min<size_t>(images[index].slicePitch, timages[index].slicePitch);
|
||||
memcpy_s(pDest, images[index].slicePitch, pSrc, csize);
|
||||
|
||||
if (cpFlags & CP_FLAGS_BAD_DXTN_TAILS)
|
||||
{
|
||||
if (images[index].width < 4 || images[index].height < 4)
|
||||
{
|
||||
csize = std::min<size_t>(images[index].slicePitch, timages[lastgood].slicePitch);
|
||||
memcpy_s(pDest, images[index].slicePitch, timages[lastgood].pixels, csize);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastgood = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsPlanar(metadata.format))
|
||||
{
|
||||
|
@ -1191,6 +1205,7 @@ namespace
|
|||
size_t index = 0;
|
||||
size_t d = metadata.depth;
|
||||
|
||||
size_t lastgood = 0;
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
for (size_t slice = 0; slice < d; ++slice, ++index)
|
||||
|
@ -1216,6 +1231,19 @@ namespace
|
|||
{
|
||||
size_t csize = std::min<size_t>(images[index].slicePitch, timages[index].slicePitch);
|
||||
memcpy_s(pDest, images[index].slicePitch, pSrc, csize);
|
||||
|
||||
if (cpFlags & CP_FLAGS_BAD_DXTN_TAILS)
|
||||
{
|
||||
if (images[index].width < 4 || images[index].height < 4)
|
||||
{
|
||||
csize = std::min<size_t>(images[index].slicePitch, timages[lastgood + slice].slicePitch);
|
||||
memcpy_s(pDest, images[index].slicePitch, timages[lastgood + slice].pixels, csize);
|
||||
}
|
||||
else if (!slice)
|
||||
{
|
||||
lastgood = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsPlanar(metadata.format))
|
||||
{
|
||||
|
@ -1438,10 +1466,25 @@ HRESULT DirectX::LoadFromDDSMemory(
|
|||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
DWORD cflags = CP_FLAGS_NONE;
|
||||
if (flags & DDS_FLAGS_LEGACY_DWORD)
|
||||
{
|
||||
cflags |= CP_FLAGS_LEGACY_DWORD;
|
||||
}
|
||||
if (flags & DDS_FLAGS_BAD_DXTN_TAILS)
|
||||
{
|
||||
cflags |= CP_FLAGS_BAD_DXTN_TAILS;
|
||||
}
|
||||
|
||||
auto pPixels = reinterpret_cast<const void*>(reinterpret_cast<const uint8_t*>(pSource) + offset);
|
||||
assert(pPixels);
|
||||
hr = CopyImage(pPixels, size - offset, mdata,
|
||||
(flags & DDS_FLAGS_LEGACY_DWORD) ? CP_FLAGS_LEGACY_DWORD : CP_FLAGS_NONE, convFlags, pal8, image);
|
||||
hr = CopyImage(pPixels,
|
||||
size - offset,
|
||||
mdata,
|
||||
cflags,
|
||||
convFlags,
|
||||
pal8,
|
||||
image);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
image.Release();
|
||||
|
@ -1560,7 +1603,7 @@ HRESULT DirectX::LoadFromDDSFile(
|
|||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if ((convFlags & CONV_FLAGS_EXPAND) || (flags & DDS_FLAGS_LEGACY_DWORD))
|
||||
if ((convFlags & CONV_FLAGS_EXPAND) || (flags & (DDS_FLAGS_LEGACY_DWORD | DDS_FLAGS_BAD_DXTN_TAILS)))
|
||||
{
|
||||
std::unique_ptr<uint8_t[]> temp(new (std::nothrow) uint8_t[remaining]);
|
||||
if (!temp)
|
||||
|
@ -1581,9 +1624,23 @@ HRESULT DirectX::LoadFromDDSFile(
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = CopyImage(temp.get(), remaining, mdata,
|
||||
(flags & DDS_FLAGS_LEGACY_DWORD) ? CP_FLAGS_LEGACY_DWORD : CP_FLAGS_NONE,
|
||||
convFlags, pal8.get(), image);
|
||||
DWORD cflags = CP_FLAGS_NONE;
|
||||
if (flags & DDS_FLAGS_LEGACY_DWORD)
|
||||
{
|
||||
cflags |= CP_FLAGS_LEGACY_DWORD;
|
||||
}
|
||||
if (flags & DDS_FLAGS_BAD_DXTN_TAILS)
|
||||
{
|
||||
cflags |= CP_FLAGS_BAD_DXTN_TAILS;
|
||||
}
|
||||
|
||||
hr = CopyImage(temp.get(),
|
||||
remaining,
|
||||
mdata,
|
||||
cflags,
|
||||
convFlags,
|
||||
pal8.get(),
|
||||
image);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
image.Release();
|
||||
|
@ -1595,7 +1652,7 @@ HRESULT DirectX::LoadFromDDSFile(
|
|||
if (remaining < image.GetPixelsSize())
|
||||
{
|
||||
image.Release();
|
||||
return E_FAIL;
|
||||
return HRESULT_FROM_WIN32( ERROR_HANDLE_EOF );
|
||||
}
|
||||
|
||||
if (!ReadFile(hFile.get(), image.GetPixels(), static_cast<DWORD>(image.GetPixelsSize()), &bytesRead, nullptr))
|
||||
|
|
|
@ -881,11 +881,20 @@ void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
|||
case DXGI_FORMAT_BC4_SNORM:
|
||||
assert(IsCompressed(fmt));
|
||||
{
|
||||
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||
rowPitch = nbw * 8;
|
||||
|
||||
slicePitch = rowPitch * nbh;
|
||||
if (flags & CP_FLAGS_BAD_DXTN_TAILS)
|
||||
{
|
||||
size_t nbw = width >> 2;
|
||||
size_t nbh = height >> 2;
|
||||
rowPitch = std::max<size_t>(1, nbw * 8);
|
||||
slicePitch = std::max<size_t>(1, rowPitch * nbh);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||
rowPitch = nbw * 8;
|
||||
slicePitch = rowPitch * nbh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -906,11 +915,20 @@ void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
|||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
assert(IsCompressed(fmt));
|
||||
{
|
||||
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||
rowPitch = nbw * 16;
|
||||
|
||||
slicePitch = rowPitch * nbh;
|
||||
if (flags & CP_FLAGS_BAD_DXTN_TAILS)
|
||||
{
|
||||
size_t nbw = width >> 2;
|
||||
size_t nbh = height >> 2;
|
||||
rowPitch = std::max<size_t>(1, nbw * 16);
|
||||
slicePitch = std::max<size_t>(1, rowPitch * nbh);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||
rowPitch = nbw * 16;
|
||||
slicePitch = rowPitch * nbh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ enum OPTIONS // Note: dwOptions below assumes 64 or less options.
|
|||
OPT_HFLIP,
|
||||
OPT_VFLIP,
|
||||
OPT_DDS_DWORD_ALIGN,
|
||||
OPT_DDS_BAD_DXTN_TAILS,
|
||||
OPT_USE_DX10,
|
||||
OPT_NOLOGO,
|
||||
OPT_TIMING,
|
||||
|
@ -116,6 +117,7 @@ SValue g_pOptions[] =
|
|||
{ L"hflip", OPT_HFLIP },
|
||||
{ L"vflip", OPT_VFLIP },
|
||||
{ L"dword", OPT_DDS_DWORD_ALIGN },
|
||||
{ L"badtails", OPT_DDS_BAD_DXTN_TAILS },
|
||||
{ L"dx10", OPT_USE_DX10 },
|
||||
{ L"nologo", OPT_NOLOGO },
|
||||
{ L"timing", OPT_TIMING },
|
||||
|
@ -529,6 +531,7 @@ void PrintUsage()
|
|||
wprintf( L"\n (DDS input only)\n");
|
||||
wprintf( L" -t{u|f} TYPELESS format is treated as UNORM or FLOAT\n");
|
||||
wprintf( L" -dword Use DWORD instead of BYTE alignment\n");
|
||||
wprintf( L" -badtails Fix for older DXTn with bad mipchain tails\n");
|
||||
wprintf( L" -xlum expand legacy L8, L16, and A8P8 formats\n");
|
||||
wprintf( L"\n (DDS output only)\n");
|
||||
wprintf( L" -dx10 Force use of 'DX10' extended header\n");
|
||||
|
@ -1178,6 +1181,8 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||
ddsFlags |= DDS_FLAGS_LEGACY_DWORD;
|
||||
if ( dwOptions & (DWORD64(1) << OPT_EXPAND_LUMINANCE) )
|
||||
ddsFlags |= DDS_FLAGS_EXPAND_LUMINANCE;
|
||||
if ( dwOptions & (DWORD64(1) << OPT_DDS_BAD_DXTN_TAILS) )
|
||||
ddsFlags |= DDS_FLAGS_BAD_DXTN_TAILS;
|
||||
|
||||
hr = LoadFromDDSFile( pConv->szSrc, ddsFlags, &info, *image );
|
||||
if ( FAILED(hr) )
|
||||
|
|
Загрузка…
Ссылка в новой задаче