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,
|
DDS_FLAGS_FORCE_DXT5_RXGB = 0x80000,
|
||||||
// Force use of 'RXGB' instead of 'DXT5' for DDS write of BC3_UNORM data
|
// 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,
|
DDS_FLAGS_ALLOW_LARGE_FILES = 0x1000000,
|
||||||
// Enables the loader to read large dimension .dds files (i.e. greater than known hardware requirements)
|
// Enables the loader to read large dimension .dds files (i.e. greater than known hardware requirements)
|
||||||
};
|
};
|
||||||
|
|||||||
@ -669,6 +669,22 @@ namespace
|
|||||||
|
|
||||||
return S_OK;
|
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;
|
flags |= DDS_FLAGS_FORCE_DX10_EXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CP_FLAGS pitchFlags = CP_FLAGS_NONE;
|
||||||
DDS_PIXELFORMAT ddpf = {};
|
DDS_PIXELFORMAT ddpf = {};
|
||||||
if (!(flags & DDS_FLAGS_FORCE_DX10_EXT))
|
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_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_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_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_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
|
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;
|
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))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -2371,6 +2401,9 @@ HRESULT DirectX::SaveToDDSMemory(
|
|||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
bool fastpath = true;
|
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)
|
for (size_t i = 0; i < nimages; ++i)
|
||||||
{
|
{
|
||||||
@ -2381,7 +2414,10 @@ HRESULT DirectX::SaveToDDSMemory(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
size_t ddsRowPitch, ddsSlicePitch;
|
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))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -2447,6 +2483,40 @@ HRESULT DirectX::SaveToDDSMemory(
|
|||||||
pDestination += pixsize;
|
pDestination += pixsize;
|
||||||
remaining -= 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
|
else
|
||||||
{
|
{
|
||||||
size_t ddsRowPitch, ddsSlicePitch;
|
size_t ddsRowPitch, ddsSlicePitch;
|
||||||
@ -2519,6 +2589,40 @@ HRESULT DirectX::SaveToDDSMemory(
|
|||||||
pDestination += pixsize;
|
pDestination += pixsize;
|
||||||
remaining -= 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
|
else
|
||||||
{
|
{
|
||||||
size_t ddsRowPitch, ddsSlicePitch;
|
size_t ddsRowPitch, ddsSlicePitch;
|
||||||
@ -2627,6 +2731,26 @@ HRESULT DirectX::SaveToDDSFile(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
#endif
|
#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
|
// Write images
|
||||||
switch (static_cast<DDS_RESOURCE_DIMENSION>(metadata.dimension))
|
switch (static_cast<DDS_RESOURCE_DIMENSION>(metadata.dimension))
|
||||||
{
|
{
|
||||||
@ -2648,7 +2772,10 @@ HRESULT DirectX::SaveToDDSFile(
|
|||||||
assert(images[index].slicePitch > 0);
|
assert(images[index].slicePitch > 0);
|
||||||
|
|
||||||
size_t ddsRowPitch, ddsSlicePitch;
|
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))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -2670,6 +2797,35 @@ HRESULT DirectX::SaveToDDSFile(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
#endif
|
#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
|
else
|
||||||
{
|
{
|
||||||
const size_t rowPitch = images[index].rowPitch;
|
const size_t rowPitch = images[index].rowPitch;
|
||||||
@ -2733,7 +2889,10 @@ HRESULT DirectX::SaveToDDSFile(
|
|||||||
assert(images[index].slicePitch > 0);
|
assert(images[index].slicePitch > 0);
|
||||||
|
|
||||||
size_t ddsRowPitch, ddsSlicePitch;
|
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))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
@ -2755,6 +2914,34 @@ HRESULT DirectX::SaveToDDSFile(
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
#endif
|
#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
|
else
|
||||||
{
|
{
|
||||||
const size_t rowPitch = images[index].rowPitch;
|
const size_t rowPitch = images[index].rowPitch;
|
||||||
|
|||||||
@ -189,6 +189,7 @@ namespace
|
|||||||
{
|
{
|
||||||
FORMAT_DXT5_NM = 1,
|
FORMAT_DXT5_NM = 1,
|
||||||
FORMAT_DXT5_RXGB,
|
FORMAT_DXT5_RXGB,
|
||||||
|
FORMAT_24BPP_LEGACY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(OPT_FLAGS_MAX <= 64, "dwOptions is a unsigned int bitfield");
|
static_assert(OPT_FLAGS_MAX <= 64, "dwOptions is a unsigned int bitfield");
|
||||||
@ -450,6 +451,7 @@ namespace
|
|||||||
{ L"BC3n", FORMAT_DXT5_NM },
|
{ L"BC3n", FORMAT_DXT5_NM },
|
||||||
{ L"DXT5nm", FORMAT_DXT5_NM },
|
{ L"DXT5nm", FORMAT_DXT5_NM },
|
||||||
{ L"RXGB", FORMAT_DXT5_RXGB },
|
{ L"RXGB", FORMAT_DXT5_RXGB },
|
||||||
|
{ L"RGB24", FORMAT_24BPP_LEGACY },
|
||||||
|
|
||||||
{ nullptr, 0 }
|
{ nullptr, 0 }
|
||||||
};
|
};
|
||||||
@ -1271,6 +1273,7 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
bool keepRecursiveDirs = false;
|
bool keepRecursiveDirs = false;
|
||||||
bool dxt5nm = false;
|
bool dxt5nm = false;
|
||||||
bool dxt5rxgb = false;
|
bool dxt5rxgb = false;
|
||||||
|
bool use24bpp = false;
|
||||||
uint32_t swizzleElements[4] = { 0, 1, 2, 3 };
|
uint32_t swizzleElements[4] = { 0, 1, 2, 3 };
|
||||||
uint32_t zeroElements[4] = {};
|
uint32_t zeroElements[4] = {};
|
||||||
uint32_t oneElements[4] = {};
|
uint32_t oneElements[4] = {};
|
||||||
@ -1488,6 +1491,11 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
dxt5rxgb = true;
|
dxt5rxgb = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FORMAT_24BPP_LEGACY:
|
||||||
|
format = DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
use24bpp = true;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wprintf(L"Invalid value specified with -f (%ls)\n\n", pValue);
|
wprintf(L"Invalid value specified with -f (%ls)\n\n", pValue);
|
||||||
PrintUsage();
|
PrintUsage();
|
||||||
@ -3775,6 +3783,10 @@ int __cdecl wmain(_In_ int argc, _In_z_count_(argc) wchar_t* argv[])
|
|||||||
{
|
{
|
||||||
ddsFlags |= DDS_FLAGS_FORCE_DXT5_RXGB;
|
ddsFlags |= DDS_FLAGS_FORCE_DXT5_RXGB;
|
||||||
}
|
}
|
||||||
|
else if (use24bpp)
|
||||||
|
{
|
||||||
|
ddsFlags |= DDS_FLAGS_FORCE_24BPP_RGB;
|
||||||
|
}
|
||||||
|
|
||||||
ddsFlags |= DDS_FLAGS_FORCE_DX9_LEGACY;
|
ddsFlags |= DDS_FLAGS_FORCE_DX9_LEGACY;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user