mirror of
https://github.com/microsoft/DirectXTex.git
synced 2025-12-06 07:11:44 +01:00
Add flag to write BGRX DDS content using R8G8B8 24bpp legacy DX9 (#641)
This commit is contained in:
parent
f04d5cb47f
commit
f180374ba5
@ -268,6 +268,9 @@ namespace DirectX
|
||||
DDS_FLAGS_FORCE_DXT5_RXGB = 0x80000,
|
||||
// Force use of 'RXGB' instead of 'DXT5' for DDS write of BC3_UNORM data
|
||||
|
||||
DDS_FLAGS_FORCE_24BPP_RGB = 0x100000,
|
||||
// Force use of 'RGB' 24bpp legacy Direct3D 9 format for DDS write of B8G8R8X8_UNORM data
|
||||
|
||||
DDS_FLAGS_ALLOW_LARGE_FILES = 0x1000000,
|
||||
// Enables the loader to read large dimension .dds files (i.e. greater than known hardware requirements)
|
||||
};
|
||||
|
||||
@ -669,6 +669,22 @@ namespace
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
inline void CopyScanline24bpp(
|
||||
_Out_writes_bytes_(width * 3) uint8_t* pDestination,
|
||||
_In_reads_bytes_(width * 4) const uint8_t* pSource,
|
||||
size_t width) noexcept
|
||||
{
|
||||
for (size_t x = 0; x < width; ++x)
|
||||
{
|
||||
pDestination[0] = pSource[0]; // B
|
||||
pDestination[1] = pSource[1]; // G
|
||||
pDestination[2] = pSource[2]; // R
|
||||
|
||||
pSource += 4;
|
||||
pDestination += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -706,6 +722,7 @@ HRESULT DirectX::EncodeDDSHeader(
|
||||
flags |= DDS_FLAGS_FORCE_DX10_EXT;
|
||||
}
|
||||
|
||||
CP_FLAGS pitchFlags = CP_FLAGS_NONE;
|
||||
DDS_PIXELFORMAT ddpf = {};
|
||||
if (!(flags & DDS_FLAGS_FORCE_DX10_EXT))
|
||||
{
|
||||
@ -729,7 +746,18 @@ HRESULT DirectX::EncodeDDSHeader(
|
||||
case DXGI_FORMAT_R8G8B8A8_SNORM: memcpy(&ddpf, &DDSPF_Q8W8V8U8, sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_R16G16_SNORM: memcpy(&ddpf, &DDSPF_V16U16, sizeof(DDS_PIXELFORMAT)); break;
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM: memcpy(&ddpf, &DDSPF_A8R8G8B8, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.1
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM: memcpy(&ddpf, &DDSPF_X8R8G8B8, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.1
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
if (flags & DDS_FLAGS_FORCE_24BPP_RGB)
|
||||
{
|
||||
|
||||
memcpy(&ddpf, &DDSPF_R8G8B8, sizeof(DDS_PIXELFORMAT)); // No DXGI equivalent
|
||||
pitchFlags |= CP_FLAGS_24BPP;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&ddpf, &DDSPF_X8R8G8B8, sizeof(DDS_PIXELFORMAT)); // DXGI 1.1
|
||||
}
|
||||
break;
|
||||
case DXGI_FORMAT_B4G4R4A4_UNORM: memcpy(&ddpf, &DDSPF_A4R4G4B4, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2
|
||||
case DXGI_FORMAT_YUY2: memcpy(&ddpf, &DDSPF_YUY2, sizeof(DDS_PIXELFORMAT)); break; // DXGI 1.2
|
||||
|
||||
@ -922,7 +950,9 @@ HRESULT DirectX::EncodeDDSHeader(
|
||||
}
|
||||
|
||||
size_t rowPitch, slicePitch;
|
||||
HRESULT hr = ComputePitch(metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
HRESULT hr = ComputePitch(metadata.format,
|
||||
metadata.width, metadata.height,
|
||||
rowPitch, slicePitch, pitchFlags);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
@ -2371,6 +2401,9 @@ HRESULT DirectX::SaveToDDSMemory(
|
||||
return hr;
|
||||
|
||||
bool fastpath = true;
|
||||
const bool use24bpp = ((metadata.format == DXGI_FORMAT_B8G8R8X8_UNORM)
|
||||
&& (flags & DDS_FLAGS_FORCE_24BPP_RGB)
|
||||
&& !(flags & (DDS_FLAGS_FORCE_DX10_EXT | DDS_FLAGS_FORCE_DX10_EXT_MISC2))) != 0;
|
||||
|
||||
for (size_t i = 0; i < nimages; ++i)
|
||||
{
|
||||
@ -2381,7 +2414,10 @@ HRESULT DirectX::SaveToDDSMemory(
|
||||
return E_FAIL;
|
||||
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
hr = ComputePitch(metadata.format, images[i].width, images[i].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE);
|
||||
hr = ComputePitch(metadata.format,
|
||||
images[i].width, images[i].height,
|
||||
ddsRowPitch, ddsSlicePitch,
|
||||
(use24bpp) ? CP_FLAGS_24BPP : CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
@ -2447,6 +2483,40 @@ HRESULT DirectX::SaveToDDSMemory(
|
||||
pDestination += pixsize;
|
||||
remaining -= pixsize;
|
||||
}
|
||||
else if (use24bpp)
|
||||
{
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
hr = ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_24BPP);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
blob.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
const size_t rowPitch = images[index].rowPitch;
|
||||
const uint8_t * __restrict sPtr = images[index].pixels;
|
||||
uint8_t * __restrict dPtr = pDestination;
|
||||
|
||||
const size_t csize = std::min<size_t>(metadata.width * 3, ddsRowPitch);
|
||||
size_t tremaining = remaining;
|
||||
for (size_t j = 0; j < images[index].height; ++j)
|
||||
{
|
||||
if (tremaining < csize)
|
||||
{
|
||||
blob.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CopyScanline24bpp(dPtr, sPtr, images[index].width);
|
||||
|
||||
sPtr += rowPitch;
|
||||
dPtr += ddsRowPitch;
|
||||
tremaining -= ddsRowPitch;
|
||||
}
|
||||
|
||||
pDestination += ddsSlicePitch;
|
||||
remaining -= ddsSlicePitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
@ -2519,6 +2589,40 @@ HRESULT DirectX::SaveToDDSMemory(
|
||||
pDestination += pixsize;
|
||||
remaining -= pixsize;
|
||||
}
|
||||
else if (use24bpp)
|
||||
{
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
hr = ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_24BPP);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
blob.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
const size_t rowPitch = images[index].rowPitch;
|
||||
const uint8_t * __restrict sPtr = images[index].pixels;
|
||||
uint8_t * __restrict dPtr = pDestination;
|
||||
|
||||
const size_t csize = std::min<size_t>(metadata.width * 3, ddsRowPitch);
|
||||
size_t tremaining = remaining;
|
||||
for (size_t j = 0; j < images[index].height; ++j)
|
||||
{
|
||||
if (tremaining < csize)
|
||||
{
|
||||
blob.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CopyScanline24bpp(dPtr, sPtr, images[index].width);
|
||||
|
||||
sPtr += rowPitch;
|
||||
dPtr += ddsRowPitch;
|
||||
tremaining -= ddsRowPitch;
|
||||
}
|
||||
|
||||
pDestination += ddsSlicePitch;
|
||||
remaining -= ddsSlicePitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
@ -2627,6 +2731,26 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
return E_FAIL;
|
||||
#endif
|
||||
|
||||
const bool use24bpp = ((metadata.format == DXGI_FORMAT_B8G8R8X8_UNORM)
|
||||
&& (flags & DDS_FLAGS_FORCE_24BPP_RGB)
|
||||
&& !(flags & (DDS_FLAGS_FORCE_DX10_EXT | DDS_FLAGS_FORCE_DX10_EXT_MISC2))) != 0;
|
||||
|
||||
std::unique_ptr<uint8_t[]> tempRow;
|
||||
if (use24bpp)
|
||||
{
|
||||
uint64_t lineSize = uint64_t(metadata.width) * 3;
|
||||
if (lineSize > UINT32_MAX)
|
||||
{
|
||||
return HRESULT_E_ARITHMETIC_OVERFLOW;
|
||||
}
|
||||
|
||||
tempRow.reset(new (std::nothrow) uint8_t[static_cast<size_t>(lineSize)]);
|
||||
if (!tempRow)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// Write images
|
||||
switch (static_cast<DDS_RESOURCE_DIMENSION>(metadata.dimension))
|
||||
{
|
||||
@ -2648,7 +2772,10 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
assert(images[index].slicePitch > 0);
|
||||
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
hr = ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE);
|
||||
hr = ComputePitch(metadata.format,
|
||||
images[index].width, images[index].height,
|
||||
ddsRowPitch, ddsSlicePitch,
|
||||
(use24bpp) ? CP_FLAGS_24BPP : CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
@ -2670,6 +2797,35 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
return E_FAIL;
|
||||
#endif
|
||||
}
|
||||
else if (use24bpp)
|
||||
{
|
||||
const size_t rowPitch = images[index].rowPitch;
|
||||
const uint8_t * __restrict sPtr = images[index].pixels;
|
||||
|
||||
assert(ddsRowPitch <= metadata.width * 3u);
|
||||
for (size_t j = 0; j < images[index].height; ++j)
|
||||
{
|
||||
CopyScanline24bpp(tempRow.get(), sPtr, images[index].width);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!WriteFile(hFile.get(), tempRow.get(), static_cast<DWORD>(ddsRowPitch), &bytesWritten, nullptr))
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
if (bytesWritten != ddsRowPitch)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
#else
|
||||
outFile.write(reinterpret_cast<const char*>(tempRow.get()), static_cast<std::streamsize>(ddsRowPitch));
|
||||
if (!outFile)
|
||||
return E_FAIL;
|
||||
#endif
|
||||
|
||||
sPtr += rowPitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t rowPitch = images[index].rowPitch;
|
||||
@ -2733,7 +2889,10 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
assert(images[index].slicePitch > 0);
|
||||
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
hr = ComputePitch(metadata.format, images[index].width, images[index].height, ddsRowPitch, ddsSlicePitch, CP_FLAGS_NONE);
|
||||
hr = ComputePitch(metadata.format,
|
||||
images[index].width, images[index].height,
|
||||
ddsRowPitch, ddsSlicePitch,
|
||||
(use24bpp) ? CP_FLAGS_24BPP : CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
@ -2755,6 +2914,34 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
return E_FAIL;
|
||||
#endif
|
||||
}
|
||||
else if (use24bpp)
|
||||
{
|
||||
const size_t rowPitch = images[index].rowPitch;
|
||||
const uint8_t * __restrict sPtr = images[index].pixels;
|
||||
|
||||
assert(ddsRowPitch <= metadata.width * 3u);
|
||||
for (size_t j = 0; j < images[index].height; ++j)
|
||||
{
|
||||
CopyScanline24bpp(tempRow.get(), sPtr, images[index].width);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!WriteFile(hFile.get(), tempRow.get(), static_cast<DWORD>(ddsRowPitch), &bytesWritten, nullptr))
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
if (bytesWritten != ddsRowPitch)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
#else
|
||||
outFile.write(reinterpret_cast<const char*>(tempRow.get()), static_cast<std::streamsize>(ddsRowPitch));
|
||||
if (!outFile)
|
||||
return E_FAIL;
|
||||
#endif
|
||||
sPtr += rowPitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t rowPitch = images[index].rowPitch;
|
||||
|
||||
@ -189,6 +189,7 @@ namespace
|
||||
{
|
||||
FORMAT_DXT5_NM = 1,
|
||||
FORMAT_DXT5_RXGB,
|
||||
FORMAT_24BPP_LEGACY,
|
||||
};
|
||||
|
||||
static_assert(OPT_FLAGS_MAX <= 64, "dwOptions is a unsigned int bitfield");
|
||||
@ -450,6 +451,7 @@ namespace
|
||||
{ L"BC3n", FORMAT_DXT5_NM },
|
||||
{ L"DXT5nm", FORMAT_DXT5_NM },
|
||||
{ L"RXGB", FORMAT_DXT5_RXGB },
|
||||
{ L"RGB24", FORMAT_24BPP_LEGACY },
|
||||
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
@ -1271,6 +1273,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
bool keepRecursiveDirs = false;
|
||||
bool dxt5nm = false;
|
||||
bool dxt5rxgb = false;
|
||||
bool use24bpp = false;
|
||||
uint32_t swizzleElements[4] = { 0, 1, 2, 3 };
|
||||
uint32_t zeroElements[4] = {};
|
||||
uint32_t oneElements[4] = {};
|
||||
@ -1488,6 +1491,11 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
dxt5rxgb = true;
|
||||
break;
|
||||
|
||||
case FORMAT_24BPP_LEGACY:
|
||||
format = DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||
use24bpp = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
wprintf(L"Invalid value specified with -f (%ls)\n\n", pValue);
|
||||
PrintUsage();
|
||||
@ -3775,6 +3783,10 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
||||
{
|
||||
ddsFlags |= DDS_FLAGS_FORCE_DXT5_RXGB;
|
||||
}
|
||||
else if (use24bpp)
|
||||
{
|
||||
ddsFlags |= DDS_FLAGS_FORCE_24BPP_RGB;
|
||||
}
|
||||
|
||||
ddsFlags |= DDS_FLAGS_FORCE_DX9_LEGACY;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user