mirror of
https://github.com/microsoft/DirectXTex
synced 2024-11-21 12:00:06 +00:00
ComputePitch now returns an HRESULT (#113)
This commit is contained in:
parent
3f8b8d36b9
commit
114a0acf6b
@ -406,7 +406,7 @@ namespace
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Get surface information for a particular format
|
||||
//--------------------------------------------------------------------------------------
|
||||
void GetSurfaceInfo(
|
||||
HRESULT GetSurfaceInfo(
|
||||
_In_ size_t width,
|
||||
_In_ size_t height,
|
||||
_In_ DXGI_FORMAT fmt,
|
||||
@ -414,9 +414,9 @@ namespace
|
||||
_Out_opt_ size_t* outRowBytes,
|
||||
_Out_opt_ size_t* outNumRows)
|
||||
{
|
||||
size_t numBytes = 0;
|
||||
size_t rowBytes = 0;
|
||||
size_t numRows = 0;
|
||||
uint64_t numBytes = 0;
|
||||
uint64_t rowBytes = 0;
|
||||
uint64_t numRows = 0;
|
||||
|
||||
bool bc = false;
|
||||
bool packed = false;
|
||||
@ -477,19 +477,22 @@ namespace
|
||||
planar = true;
|
||||
bpe = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bc)
|
||||
{
|
||||
size_t numBlocksWide = 0;
|
||||
uint64_t numBlocksWide = 0;
|
||||
if (width > 0)
|
||||
{
|
||||
numBlocksWide = std::max<size_t>(1, (width + 3) / 4);
|
||||
numBlocksWide = std::max<uint64_t>(1u, (uint64_t(width) + 3u) / 4u);
|
||||
}
|
||||
size_t numBlocksHigh = 0;
|
||||
uint64_t numBlocksHigh = 0;
|
||||
if (height > 0)
|
||||
{
|
||||
numBlocksHigh = std::max<size_t>(1, (height + 3) / 4);
|
||||
numBlocksHigh = std::max<uint64_t>(1u, (uint64_t(height) + 3u) / 4u);
|
||||
}
|
||||
rowBytes = numBlocksWide * bpe;
|
||||
numRows = numBlocksHigh;
|
||||
@ -497,42 +500,55 @@ namespace
|
||||
}
|
||||
else if (packed)
|
||||
{
|
||||
rowBytes = ((width + 1) >> 1) * bpe;
|
||||
numRows = height;
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
else if (fmt == DXGI_FORMAT_NV11)
|
||||
{
|
||||
rowBytes = ((width + 3) >> 2) * 4;
|
||||
numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
rowBytes = ((uint64_t(width) + 3u) >> 2) * 4u;
|
||||
numRows = uint64_t(height) * 2u; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
numBytes = rowBytes * numRows;
|
||||
}
|
||||
else if (planar)
|
||||
{
|
||||
rowBytes = ((width + 1) >> 1) * bpe;
|
||||
numBytes = (rowBytes * height) + ((rowBytes * height + 1) >> 1);
|
||||
numRows = height + ((height + 1) >> 1);
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numBytes = (rowBytes * uint64_t(height)) + ((rowBytes * uint64_t(height) + 1u) >> 1);
|
||||
numRows = height + ((uint64_t(height) + 1u) >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bpp = BitsPerPixel(fmt);
|
||||
rowBytes = (width * bpp + 7) / 8; // round up to nearest byte
|
||||
numRows = height;
|
||||
if (!bpp)
|
||||
return E_INVALIDARG;
|
||||
|
||||
rowBytes = (uint64_t(width) * bpp + 7u) / 8u; // round up to nearest byte
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
|
||||
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
|
||||
if (numBytes > UINT32_MAX || rowBytes > UINT32_MAX || numRows > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
#else
|
||||
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
|
||||
#endif
|
||||
|
||||
if (outNumBytes)
|
||||
{
|
||||
*outNumBytes = numBytes;
|
||||
*outNumBytes = static_cast<size_t>(numBytes);
|
||||
}
|
||||
if (outRowBytes)
|
||||
{
|
||||
*outRowBytes = rowBytes;
|
||||
*outRowBytes = static_cast<size_t>(rowBytes);
|
||||
}
|
||||
if (outNumRows)
|
||||
{
|
||||
*outNumRows = numRows;
|
||||
*outNumRows = static_cast<size_t>(numRows);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -851,7 +867,9 @@ namespace
|
||||
size_t d = depth;
|
||||
for (size_t i = 0; i < mipCount; i++)
|
||||
{
|
||||
GetSurfaceInfo(w, h, format, &NumBytes, &RowBytes, nullptr);
|
||||
HRESULT hr = GetSurfaceInfo(w, h, format, &NumBytes, &RowBytes, nullptr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (NumBytes > UINT32_MAX || RowBytes > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
@ -1357,7 +1375,9 @@ namespace
|
||||
{
|
||||
size_t numBytes = 0;
|
||||
size_t rowBytes = 0;
|
||||
GetSurfaceInfo(width, height, format, &numBytes, &rowBytes, nullptr);
|
||||
hr = GetSurfaceInfo(width, height, format, &numBytes, &rowBytes, nullptr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (numBytes > bitSize)
|
||||
{
|
||||
|
@ -336,6 +336,7 @@ namespace
|
||||
|
||||
case DXGI_FORMAT_P010:
|
||||
case DXGI_FORMAT_P016:
|
||||
case DXGI_FORMAT_V408:
|
||||
return 24;
|
||||
|
||||
case DXGI_FORMAT_R8G8_TYPELESS:
|
||||
@ -354,6 +355,8 @@ namespace
|
||||
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
||||
case DXGI_FORMAT_A8P8:
|
||||
case DXGI_FORMAT_B4G4R4A4_UNORM:
|
||||
case DXGI_FORMAT_P208:
|
||||
case DXGI_FORMAT_V208:
|
||||
return 16;
|
||||
|
||||
case DXGI_FORMAT_NV12:
|
||||
@ -409,17 +412,17 @@ namespace
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Get surface information for a particular format
|
||||
//--------------------------------------------------------------------------------------
|
||||
void GetSurfaceInfo(
|
||||
HRESULT GetSurfaceInfo(
|
||||
_In_ size_t width,
|
||||
_In_ size_t height,
|
||||
_In_ DXGI_FORMAT fmt,
|
||||
size_t* outNumBytes,
|
||||
_Out_opt_ size_t* outRowBytes,
|
||||
_Out_opt_ size_t* outNumRows )
|
||||
_Out_opt_ size_t* outNumRows)
|
||||
{
|
||||
size_t numBytes = 0;
|
||||
size_t rowBytes = 0;
|
||||
size_t numRows = 0;
|
||||
uint64_t numBytes = 0;
|
||||
uint64_t rowBytes = 0;
|
||||
uint64_t numRows = 0;
|
||||
|
||||
bool bc = false;
|
||||
bool packed = false;
|
||||
@ -433,7 +436,7 @@ namespace
|
||||
case DXGI_FORMAT_BC4_TYPELESS:
|
||||
case DXGI_FORMAT_BC4_UNORM:
|
||||
case DXGI_FORMAT_BC4_SNORM:
|
||||
bc=true;
|
||||
bc = true;
|
||||
bpe = 8;
|
||||
break;
|
||||
|
||||
@ -471,6 +474,7 @@ namespace
|
||||
|
||||
case DXGI_FORMAT_NV12:
|
||||
case DXGI_FORMAT_420_OPAQUE:
|
||||
case DXGI_FORMAT_P208:
|
||||
planar = true;
|
||||
bpe = 2;
|
||||
break;
|
||||
@ -480,19 +484,22 @@ namespace
|
||||
planar = true;
|
||||
bpe = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bc)
|
||||
{
|
||||
size_t numBlocksWide = 0;
|
||||
uint64_t numBlocksWide = 0;
|
||||
if (width > 0)
|
||||
{
|
||||
numBlocksWide = std::max<size_t>( 1, (width + 3) / 4 );
|
||||
numBlocksWide = std::max<uint64_t>(1u, (uint64_t(width) + 3u) / 4u);
|
||||
}
|
||||
size_t numBlocksHigh = 0;
|
||||
uint64_t numBlocksHigh = 0;
|
||||
if (height > 0)
|
||||
{
|
||||
numBlocksHigh = std::max<size_t>( 1, (height + 3) / 4 );
|
||||
numBlocksHigh = std::max<uint64_t>(1u, (uint64_t(height) + 3u) / 4u);
|
||||
}
|
||||
rowBytes = numBlocksWide * bpe;
|
||||
numRows = numBlocksHigh;
|
||||
@ -500,42 +507,55 @@ namespace
|
||||
}
|
||||
else if (packed)
|
||||
{
|
||||
rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
|
||||
numRows = height;
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
else if ( fmt == DXGI_FORMAT_NV11 )
|
||||
else if (fmt == DXGI_FORMAT_NV11)
|
||||
{
|
||||
rowBytes = ( ( width + 3 ) >> 2 ) * 4;
|
||||
numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
rowBytes = ((uint64_t(width) + 3u) >> 2) * 4u;
|
||||
numRows = uint64_t(height) * 2u; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
numBytes = rowBytes * numRows;
|
||||
}
|
||||
else if (planar)
|
||||
{
|
||||
rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
|
||||
numBytes = ( rowBytes * height ) + ( ( rowBytes * height + 1 ) >> 1 );
|
||||
numRows = height + ( ( height + 1 ) >> 1 );
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numBytes = (rowBytes * uint64_t(height)) + ((rowBytes * uint64_t(height) + 1u) >> 1);
|
||||
numRows = height + ((uint64_t(height) + 1u) >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bpp = BitsPerPixel( fmt );
|
||||
rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte
|
||||
numRows = height;
|
||||
size_t bpp = BitsPerPixel(fmt);
|
||||
if (!bpp)
|
||||
return E_INVALIDARG;
|
||||
|
||||
rowBytes = (uint64_t(width) * bpp + 7u) / 8u; // round up to nearest byte
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
|
||||
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
|
||||
if (numBytes > UINT32_MAX || rowBytes > UINT32_MAX || numRows > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
#else
|
||||
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
|
||||
#endif
|
||||
|
||||
if (outNumBytes)
|
||||
{
|
||||
*outNumBytes = numBytes;
|
||||
*outNumBytes = static_cast<size_t>(numBytes);
|
||||
}
|
||||
if (outRowBytes)
|
||||
{
|
||||
*outRowBytes = rowBytes;
|
||||
*outRowBytes = static_cast<size_t>(rowBytes);
|
||||
}
|
||||
if (outNumRows)
|
||||
{
|
||||
*outNumRows = numRows;
|
||||
*outNumRows = static_cast<size_t>(numRows);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -849,12 +869,6 @@ namespace
|
||||
case DXGI_FORMAT_NV12:
|
||||
case DXGI_FORMAT_P010:
|
||||
case DXGI_FORMAT_P016:
|
||||
|
||||
#if defined(_XBOX_ONE) && defined(_TITLE)
|
||||
case DXGI_FORMAT_D16_UNORM_S8_UINT:
|
||||
case DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
|
||||
case DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
||||
#endif
|
||||
if (!slicePlane)
|
||||
{
|
||||
// Plane 0
|
||||
@ -930,7 +944,9 @@ namespace
|
||||
size_t d = depth;
|
||||
for (size_t i = 0; i < mipCount; i++)
|
||||
{
|
||||
GetSurfaceInfo(w, h, format, &NumBytes, &RowBytes, nullptr);
|
||||
HRESULT hr = GetSurfaceInfo(w, h, format, &NumBytes, &RowBytes, nullptr);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (NumBytes > UINT32_MAX || RowBytes > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
@ -71,7 +71,7 @@ namespace DirectX
|
||||
CP_FLAGS_8BPP = 0x40000, // Override with a legacy 8 bits-per-pixel format size
|
||||
};
|
||||
|
||||
void __cdecl ComputePitch(
|
||||
HRESULT __cdecl ComputePitch(
|
||||
_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height,
|
||||
_Out_ size_t& rowPitch, _Out_ size_t& slicePitch, _In_ DWORD flags = CP_FLAGS_NONE);
|
||||
|
||||
|
@ -686,7 +686,9 @@ HRESULT DirectX::_EncodeDDSHeader(
|
||||
}
|
||||
|
||||
size_t rowPitch, slicePitch;
|
||||
ComputePitch(metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
HRESULT hr = ComputePitch(metadata.format, metadata.width, metadata.height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (slicePitch > UINT32_MAX
|
||||
|| rowPitch > UINT32_MAX)
|
||||
@ -1140,7 +1142,9 @@ namespace
|
||||
}
|
||||
|
||||
size_t pixelSize, nimages;
|
||||
_DetermineImageArray(metadata, cpFlags, nimages, pixelSize);
|
||||
if (!_DetermineImageArray(metadata, cpFlags, nimages, pixelSize))
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
if ((nimages == 0) || (nimages != image.GetImageCount()))
|
||||
{
|
||||
return E_FAIL;
|
||||
@ -1741,6 +1745,12 @@ HRESULT DirectX::LoadFromDDSFile(
|
||||
return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
|
||||
}
|
||||
|
||||
if (image.GetPixelsSize() > UINT32_MAX)
|
||||
{
|
||||
image.Release();
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
}
|
||||
|
||||
if (!ReadFile(hFile.get(), image.GetPixels(), static_cast<DWORD>(image.GetPixelsSize()), &bytesRead, nullptr))
|
||||
{
|
||||
image.Release();
|
||||
@ -1797,7 +1807,9 @@ HRESULT DirectX::SaveToDDSMemory(
|
||||
return E_FAIL;
|
||||
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
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, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
assert(images[i].rowPitch > 0);
|
||||
assert(images[i].slicePitch > 0);
|
||||
@ -1868,7 +1880,12 @@ HRESULT DirectX::SaveToDDSMemory(
|
||||
else
|
||||
{
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
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, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
blob.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
size_t rowPitch = images[index].rowPitch;
|
||||
|
||||
@ -1937,7 +1954,12 @@ HRESULT DirectX::SaveToDDSMemory(
|
||||
else
|
||||
{
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
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, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
blob.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
size_t rowPitch = images[index].rowPitch;
|
||||
|
||||
@ -2049,9 +2071,11 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
assert(images[index].slicePitch > 0);
|
||||
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
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, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (images[index].slicePitch == ddsSlicePitch)
|
||||
if ((images[index].slicePitch == ddsSlicePitch) && (ddsSlicePitch <= UINT32_MAX))
|
||||
{
|
||||
if (!WriteFile(hFile.get(), images[index].pixels, static_cast<DWORD>(ddsSlicePitch), &bytesWritten, nullptr))
|
||||
{
|
||||
@ -2072,6 +2096,9 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (ddsRowPitch > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
const uint8_t * __restrict sPtr = images[index].pixels;
|
||||
|
||||
size_t lines = ComputeScanlines(metadata.format, images[index].height);
|
||||
@ -2117,9 +2144,11 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
assert(images[index].slicePitch > 0);
|
||||
|
||||
size_t ddsRowPitch, ddsSlicePitch;
|
||||
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, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (images[index].slicePitch == ddsSlicePitch)
|
||||
if ((images[index].slicePitch == ddsSlicePitch) && (ddsSlicePitch <= UINT32_MAX))
|
||||
{
|
||||
if (!WriteFile(hFile.get(), images[index].pixels, static_cast<DWORD>(ddsSlicePitch), &bytesWritten, nullptr))
|
||||
{
|
||||
@ -2140,6 +2169,9 @@ HRESULT DirectX::SaveToDDSFile(
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (ddsRowPitch > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
const uint8_t * __restrict sPtr = images[index].pixels;
|
||||
|
||||
size_t lines = ComputeScanlines(metadata.format, images[index].height);
|
||||
|
@ -1011,8 +1011,13 @@ HRESULT DirectX::SaveToHDRFile(const Image& image, const wchar_t* szFile)
|
||||
|
||||
auto_delete_file delonfail(hFile.get());
|
||||
|
||||
size_t rowPitch = image.width * 4;
|
||||
size_t slicePitch = image.height * rowPitch;
|
||||
uint64_t pitch = uint64_t(image.width) * 4u;
|
||||
uint64_t slicePitch = uint64_t(image.height) * pitch;
|
||||
|
||||
if (pitch > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
size_t rowPitch = static_cast<size_t>(pitch);
|
||||
|
||||
if (slicePitch < 65535)
|
||||
{
|
||||
@ -1088,6 +1093,9 @@ HRESULT DirectX::SaveToHDRFile(const Image& image, const wchar_t* szFile)
|
||||
size_t encSize = EncodeRLE(enc, rgbe, rowPitch, image.width);
|
||||
if (encSize > 0)
|
||||
{
|
||||
if (encSize > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
if (!WriteFile(hFile.get(), enc, static_cast<DWORD>(encSize), &bytesWritten, nullptr))
|
||||
{
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
|
@ -24,7 +24,7 @@ using namespace DirectX;
|
||||
// Determines number of image array entries and pixel size
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
void DirectX::_DetermineImageArray(
|
||||
bool DirectX::_DetermineImageArray(
|
||||
const TexMetadata& metadata,
|
||||
DWORD cpFlags,
|
||||
size_t& nImages,
|
||||
@ -34,8 +34,8 @@ void DirectX::_DetermineImageArray(
|
||||
assert(metadata.arraySize > 0);
|
||||
assert(metadata.mipLevels > 0);
|
||||
|
||||
size_t _pixelSize = 0;
|
||||
size_t _nimages = 0;
|
||||
uint64_t totalPixelSize = 0;
|
||||
size_t nimages = 0;
|
||||
|
||||
switch (metadata.dimension)
|
||||
{
|
||||
@ -49,10 +49,14 @@ void DirectX::_DetermineImageArray(
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
size_t rowPitch, slicePitch;
|
||||
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
|
||||
if (FAILED(ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags)))
|
||||
{
|
||||
nImages = pixelSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
_pixelSize += slicePitch;
|
||||
++_nimages;
|
||||
totalPixelSize += uint64_t(slicePitch);
|
||||
++nimages;
|
||||
|
||||
if (h > 1)
|
||||
h >>= 1;
|
||||
@ -72,12 +76,16 @@ void DirectX::_DetermineImageArray(
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
size_t rowPitch, slicePitch;
|
||||
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
|
||||
if (FAILED(ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags)))
|
||||
{
|
||||
nImages = pixelSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t slice = 0; slice < d; ++slice)
|
||||
{
|
||||
_pixelSize += slicePitch;
|
||||
++_nimages;
|
||||
totalPixelSize += uint64_t(slicePitch);
|
||||
++nimages;
|
||||
}
|
||||
|
||||
if (h > 1)
|
||||
@ -93,12 +101,25 @@ void DirectX::_DetermineImageArray(
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
nImages = pixelSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
nImages = _nimages;
|
||||
pixelSize = _pixelSize;
|
||||
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
|
||||
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
|
||||
if (totalPixelSize > UINT32_MAX)
|
||||
{
|
||||
nImages = pixelSize = 0;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
|
||||
#endif
|
||||
|
||||
nImages = nimages;
|
||||
pixelSize = static_cast<size_t>(totalPixelSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -147,7 +168,8 @@ bool DirectX::_SetupImageArray(
|
||||
}
|
||||
|
||||
size_t rowPitch, slicePitch;
|
||||
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
|
||||
if (FAILED(ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags)))
|
||||
return false;
|
||||
|
||||
images[index].width = w;
|
||||
images[index].height = h;
|
||||
@ -186,7 +208,8 @@ bool DirectX::_SetupImageArray(
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
size_t rowPitch, slicePitch;
|
||||
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
|
||||
if (FAILED(ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags)))
|
||||
return false;
|
||||
|
||||
for (size_t slice = 0; slice < d; ++slice)
|
||||
{
|
||||
@ -318,7 +341,8 @@ HRESULT ScratchImage::Initialize(const TexMetadata& mdata, DWORD flags)
|
||||
m_metadata.dimension = mdata.dimension;
|
||||
|
||||
size_t pixelSize, nimages;
|
||||
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
|
||||
if (!_DetermineImageArray(m_metadata, flags, nimages, pixelSize))
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
m_image = new (std::nothrow) Image[nimages];
|
||||
if (!m_image)
|
||||
@ -384,7 +408,8 @@ HRESULT ScratchImage::Initialize2D(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
m_metadata.dimension = TEX_DIMENSION_TEXTURE2D;
|
||||
|
||||
size_t pixelSize, nimages;
|
||||
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
|
||||
if (!_DetermineImageArray(m_metadata, flags, nimages, pixelSize))
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
m_image = new (std::nothrow) Image[nimages];
|
||||
if (!m_image)
|
||||
@ -434,7 +459,8 @@ HRESULT ScratchImage::Initialize3D(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
m_metadata.dimension = TEX_DIMENSION_TEXTURE3D;
|
||||
|
||||
size_t pixelSize, nimages;
|
||||
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
|
||||
if (!_DetermineImageArray(m_metadata, flags, nimages, pixelSize))
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
m_image = new (std::nothrow) Image[nimages];
|
||||
if (!m_image)
|
||||
|
@ -178,7 +178,7 @@ namespace DirectX
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Image helper functions
|
||||
void __cdecl _DetermineImageArray(
|
||||
_Success_(return != false) bool __cdecl _DetermineImageArray(
|
||||
_In_ const TexMetadata& metadata, _In_ DWORD cpFlags,
|
||||
_Out_ size_t& nImages, _Out_ size_t& pixelSize);
|
||||
|
||||
|
@ -272,7 +272,9 @@ namespace
|
||||
else
|
||||
{
|
||||
size_t slicePitch;
|
||||
ComputePitch(image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
HRESULT hr = ComputePitch(image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
auto sPtr = static_cast<const uint8_t*>(pSource);
|
||||
@ -596,7 +598,9 @@ namespace
|
||||
else
|
||||
{
|
||||
size_t slicePitch;
|
||||
ComputePitch(image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
HRESULT hr = ComputePitch(image->format, image->width, image->height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
auto sPtr = static_cast<const uint8_t*>(pSource);
|
||||
@ -1050,6 +1054,18 @@ HRESULT DirectX::LoadFromTGAFile(
|
||||
if (!(convFlags & (CONV_FLAGS_RLE | CONV_FLAGS_EXPAND | CONV_FLAGS_INVERTX)) && (convFlags & CONV_FLAGS_INVERTY))
|
||||
{
|
||||
// This case we can read directly into the image buffer in place
|
||||
if (remaining < image.GetPixelsSize())
|
||||
{
|
||||
image.Release();
|
||||
return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
|
||||
}
|
||||
|
||||
if (image.GetPixelsSize() > UINT32_MAX)
|
||||
{
|
||||
image.Release();
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
}
|
||||
|
||||
if (!ReadFile(hFile.get(), image.GetPixels(), static_cast<DWORD>(image.GetPixelsSize()), &bytesRead, nullptr))
|
||||
{
|
||||
image.Release();
|
||||
@ -1253,7 +1269,9 @@ HRESULT DirectX::SaveToTGAMemory(const Image& image, Blob& blob)
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputePitch(image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
hr = ComputePitch(image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = blob.Initialize(sizeof(TGA_HEADER) + slicePitch);
|
||||
@ -1328,12 +1346,25 @@ HRESULT DirectX::SaveToTGAFile(const Image& image, const wchar_t* szFile)
|
||||
size_t rowPitch, slicePitch;
|
||||
if (convFlags & CONV_FLAGS_888)
|
||||
{
|
||||
rowPitch = image.width * 3;
|
||||
slicePitch = image.height * rowPitch;
|
||||
uint64_t pitch = uint64_t(image.width) * 3u;
|
||||
uint64_t slice = uint64_t(image.height) * pitch;
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
|
||||
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
|
||||
if (pitch > UINT32_MAX || slice > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
#else
|
||||
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
|
||||
#endif
|
||||
|
||||
rowPitch = static_cast<size_t>(pitch);
|
||||
slicePitch = static_cast<size_t>(slice);
|
||||
}
|
||||
else
|
||||
{
|
||||
ComputePitch(image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
hr = ComputePitch(image.format, image.width, image.height, rowPitch, slicePitch, CP_FLAGS_NONE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (slicePitch < 65535)
|
||||
@ -1375,6 +1406,9 @@ HRESULT DirectX::SaveToTGAFile(const Image& image, const wchar_t* szFile)
|
||||
if (bytesWritten != sizeof(TGA_HEADER))
|
||||
return E_FAIL;
|
||||
|
||||
if (rowPitch > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
||||
// Write pixels
|
||||
const uint8_t* pPixels = image.pixels;
|
||||
|
||||
|
@ -870,9 +870,12 @@ size_t DirectX::BitsPerColor(DXGI_FORMAT fmt)
|
||||
// based on DXGI format, width, and height
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
HRESULT DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
size_t& rowPitch, size_t& slicePitch, DWORD flags)
|
||||
{
|
||||
uint64_t pitch = 0;
|
||||
uint64_t slice = 0;
|
||||
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_BC1_TYPELESS:
|
||||
@ -887,15 +890,15 @@ void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
{
|
||||
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);
|
||||
pitch = std::max<uint64_t>(1u, uint64_t(nbw) * 8u);
|
||||
slice = std::max<uint64_t>(1u, pitch * uint64_t(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;
|
||||
uint64_t nbw = std::max<uint64_t>(1u, (uint64_t(width) + 3u) / 4u);
|
||||
uint64_t nbh = std::max<uint64_t>(1u, (uint64_t(height) + 3u) / 4u);
|
||||
pitch = nbw * 8u;
|
||||
slice = pitch * nbh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -921,15 +924,15 @@ void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
{
|
||||
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);
|
||||
pitch = std::max<uint64_t>(1u, uint64_t(nbw) * 16u);
|
||||
slice = std::max<uint64_t>(1u, pitch * uint64_t(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;
|
||||
uint64_t nbw = std::max<uint64_t>(1u, (uint64_t(width) + 3u) / 4u);
|
||||
uint64_t nbh = std::max<uint64_t>(1u, (uint64_t(height) + 3u) / 4u);
|
||||
pitch = nbw * 16u;
|
||||
slice = pitch * nbh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -938,22 +941,22 @@ void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
case DXGI_FORMAT_G8R8_G8B8_UNORM:
|
||||
case DXGI_FORMAT_YUY2:
|
||||
assert(IsPacked(fmt));
|
||||
rowPitch = ((width + 1) >> 1) * 4;
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = ((uint64_t(width) + 1u) >> 1) * 4u;
|
||||
slice = pitch * uint64_t(height);
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_Y210:
|
||||
case DXGI_FORMAT_Y216:
|
||||
assert(IsPacked(fmt));
|
||||
rowPitch = ((width + 1) >> 1) * 8;
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = ((uint64_t(width) + 1u) >> 1) * 8u;
|
||||
slice = pitch * uint64_t(height);
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_NV12:
|
||||
case DXGI_FORMAT_420_OPAQUE:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ((width + 1) >> 1) * 2;
|
||||
slicePitch = rowPitch * (height + ((height + 1) >> 1));
|
||||
pitch = ((uint64_t(width) + 1u) >> 1) * 2u;
|
||||
slice = pitch * (uint64_t(height) + ((uint64_t(height) + 1u) >> 1));
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_P010:
|
||||
@ -962,39 +965,37 @@ void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
|
||||
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ((width + 1) >> 1) * 4;
|
||||
slicePitch = rowPitch * (height + ((height + 1) >> 1));
|
||||
pitch = ((uint64_t(width) + 1u) >> 1) * 4u;
|
||||
slice = pitch * (uint64_t(height) + ((uint64_t(height) + 1u) >> 1));
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_NV11:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ((width + 3) >> 2) * 4;
|
||||
slicePitch = rowPitch * height * 2;
|
||||
pitch = ((uint64_t(width) + 3u) >> 2) * 4u;
|
||||
slice = pitch * uint64_t(height) * 2u;
|
||||
break;
|
||||
|
||||
case WIN10_DXGI_FORMAT_P208:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ((width + 1) >> 1) * 2;
|
||||
slicePitch = rowPitch * height * 2;
|
||||
pitch = ((uint64_t(width) + 1u) >> 1) * 2u;
|
||||
slice = pitch * uint64_t(height) * 2u;
|
||||
break;
|
||||
|
||||
case WIN10_DXGI_FORMAT_V208:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = width;
|
||||
slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2));
|
||||
pitch = uint64_t(width);
|
||||
slice = pitch * (uint64_t(height) + (((uint64_t(height) + 1u) >> 1) * 2u));
|
||||
break;
|
||||
|
||||
case WIN10_DXGI_FORMAT_V408:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = width;
|
||||
slicePitch = rowPitch * (height + ((height >> 1) * 4));
|
||||
pitch = uint64_t(width);
|
||||
slice = pitch * (uint64_t(height) + (uint64_t(height >> 1) * 4u));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(IsValid(fmt));
|
||||
assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt));
|
||||
{
|
||||
|
||||
size_t bpp;
|
||||
|
||||
if (flags & CP_FLAGS_24BPP)
|
||||
@ -1006,45 +1007,64 @@ void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
else
|
||||
bpp = BitsPerPixel(fmt);
|
||||
|
||||
if (!bpp)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (flags & (CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K))
|
||||
{
|
||||
if (flags & CP_FLAGS_PAGE4K)
|
||||
{
|
||||
rowPitch = ((width * bpp + 32767) / 32768) * 4096;
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = ((uint64_t(width) * bpp + 32767u) / 32768u) * 4096u;
|
||||
slice = pitch * uint64_t(height);
|
||||
}
|
||||
else if (flags & CP_FLAGS_ZMM)
|
||||
{
|
||||
rowPitch = ((width * bpp + 511) / 512) * 64;
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = ((uint64_t(width) * bpp + 511u) / 512u) * 64u;
|
||||
slice = pitch * uint64_t(height);
|
||||
}
|
||||
else if (flags & CP_FLAGS_YMM)
|
||||
{
|
||||
rowPitch = ((width * bpp + 255) / 256) * 32;
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = ((uint64_t(width) * bpp + 255u) / 256u) * 32u;
|
||||
slice = pitch * uint64_t(height);
|
||||
}
|
||||
else if (flags & CP_FLAGS_PARAGRAPH)
|
||||
{
|
||||
rowPitch = ((width * bpp + 127) / 128) * 16;
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = ((uint64_t(width) * bpp + 127u) / 128u) * 16u;
|
||||
slice = pitch * uint64_t(height);
|
||||
}
|
||||
else // DWORD alignment
|
||||
{
|
||||
// Special computation for some incorrectly created DDS files based on
|
||||
// legacy DirectDraw assumptions about pitch alignment
|
||||
rowPitch = ((width * bpp + 31) / 32) * sizeof(uint32_t);
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = ((uint64_t(width) * bpp + 31u) / 32u) * sizeof(uint32_t);
|
||||
slice = pitch * uint64_t(height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default byte alignment
|
||||
rowPitch = (width * bpp + 7) / 8;
|
||||
slicePitch = rowPitch * height;
|
||||
pitch = (uint64_t(width) * bpp + 7u) / 8u;
|
||||
slice = pitch * uint64_t(height);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
|
||||
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
|
||||
if (pitch > UINT32_MAX || slice > UINT32_MAX)
|
||||
{
|
||||
rowPitch = slicePitch = 0;
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
}
|
||||
#else
|
||||
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
|
||||
#endif
|
||||
|
||||
rowPitch = static_cast<size_t>(pitch);
|
||||
slicePitch = static_cast<size_t>(slice);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -434,17 +434,17 @@ namespace
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Get surface information for a particular format
|
||||
//--------------------------------------------------------------------------------------
|
||||
void GetSurfaceInfo(
|
||||
HRESULT GetSurfaceInfo(
|
||||
_In_ size_t width,
|
||||
_In_ size_t height,
|
||||
_In_ DXGI_FORMAT fmt,
|
||||
_Out_opt_ size_t* outNumBytes,
|
||||
_Out_opt_ size_t* outRowBytes,
|
||||
_Out_opt_ size_t* outNumRows )
|
||||
_Out_opt_ size_t* outNumRows)
|
||||
{
|
||||
size_t numBytes = 0;
|
||||
size_t rowBytes = 0;
|
||||
size_t numRows = 0;
|
||||
uint64_t numBytes = 0;
|
||||
uint64_t rowBytes = 0;
|
||||
uint64_t numRows = 0;
|
||||
|
||||
bool bc = false;
|
||||
bool packed = false;
|
||||
@ -458,7 +458,7 @@ namespace
|
||||
case DXGI_FORMAT_BC4_TYPELESS:
|
||||
case DXGI_FORMAT_BC4_UNORM:
|
||||
case DXGI_FORMAT_BC4_SNORM:
|
||||
bc=true;
|
||||
bc = true;
|
||||
bpe = 8;
|
||||
break;
|
||||
|
||||
@ -505,19 +505,22 @@ namespace
|
||||
planar = true;
|
||||
bpe = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bc)
|
||||
{
|
||||
size_t numBlocksWide = 0;
|
||||
uint64_t numBlocksWide = 0;
|
||||
if (width > 0)
|
||||
{
|
||||
numBlocksWide = std::max<size_t>( 1, (width + 3) / 4 );
|
||||
numBlocksWide = std::max<uint64_t>(1u, (uint64_t(width) + 3u) / 4u);
|
||||
}
|
||||
size_t numBlocksHigh = 0;
|
||||
uint64_t numBlocksHigh = 0;
|
||||
if (height > 0)
|
||||
{
|
||||
numBlocksHigh = std::max<size_t>( 1, (height + 3) / 4 );
|
||||
numBlocksHigh = std::max<uint64_t>(1u, (uint64_t(height) + 3u) / 4u);
|
||||
}
|
||||
rowBytes = numBlocksWide * bpe;
|
||||
numRows = numBlocksHigh;
|
||||
@ -525,42 +528,55 @@ namespace
|
||||
}
|
||||
else if (packed)
|
||||
{
|
||||
rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
|
||||
numRows = height;
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
else if ( fmt == DXGI_FORMAT_NV11 )
|
||||
else if (fmt == DXGI_FORMAT_NV11)
|
||||
{
|
||||
rowBytes = ( ( width + 3 ) >> 2 ) * 4;
|
||||
numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
rowBytes = ((uint64_t(width) + 3u) >> 2) * 4u;
|
||||
numRows = uint64_t(height) * 2u; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
numBytes = rowBytes * numRows;
|
||||
}
|
||||
else if (planar)
|
||||
{
|
||||
rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
|
||||
numBytes = ( rowBytes * height ) + ( ( rowBytes * height + 1 ) >> 1 );
|
||||
numRows = height + ( ( height + 1 ) >> 1 );
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numBytes = (rowBytes * uint64_t(height)) + ((rowBytes * uint64_t(height) + 1u) >> 1);
|
||||
numRows = height + ((uint64_t(height) + 1u) >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bpp = BitsPerPixel( fmt );
|
||||
rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte
|
||||
numRows = height;
|
||||
size_t bpp = BitsPerPixel(fmt);
|
||||
if (!bpp)
|
||||
return E_INVALIDARG;
|
||||
|
||||
rowBytes = (uint64_t(width) * bpp + 7u) / 8u; // round up to nearest byte
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
|
||||
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
|
||||
if (numBytes > UINT32_MAX || rowBytes > UINT32_MAX || numRows > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
#else
|
||||
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
|
||||
#endif
|
||||
|
||||
if (outNumBytes)
|
||||
{
|
||||
*outNumBytes = numBytes;
|
||||
*outNumBytes = static_cast<size_t>(numBytes);
|
||||
}
|
||||
if (outRowBytes)
|
||||
{
|
||||
*outRowBytes = rowBytes;
|
||||
*outRowBytes = static_cast<size_t>(rowBytes);
|
||||
}
|
||||
if (outNumRows)
|
||||
{
|
||||
*outNumRows = numRows;
|
||||
*outNumRows = static_cast<size_t>(numRows);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -845,7 +861,9 @@ HRESULT DirectX::SaveDDSTextureToFile(
|
||||
}
|
||||
|
||||
size_t rowPitch, slicePitch, rowCount;
|
||||
GetSurfaceInfo( desc.Width, desc.Height, desc.Format, &slicePitch, &rowPitch, &rowCount );
|
||||
hr = GetSurfaceInfo( desc.Width, desc.Height, desc.Format, &slicePitch, &rowPitch, &rowCount );
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (rowPitch > UINT32_MAX || slicePitch > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
@ -325,6 +325,7 @@ namespace
|
||||
|
||||
case DXGI_FORMAT_P010:
|
||||
case DXGI_FORMAT_P016:
|
||||
case DXGI_FORMAT_V408:
|
||||
return 24;
|
||||
|
||||
case DXGI_FORMAT_R8G8_TYPELESS:
|
||||
@ -343,6 +344,8 @@ namespace
|
||||
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
||||
case DXGI_FORMAT_A8P8:
|
||||
case DXGI_FORMAT_B4G4R4A4_UNORM:
|
||||
case DXGI_FORMAT_P208:
|
||||
case DXGI_FORMAT_V208:
|
||||
return 16;
|
||||
|
||||
case DXGI_FORMAT_NV12:
|
||||
@ -434,17 +437,17 @@ namespace
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Get surface information for a particular format
|
||||
//--------------------------------------------------------------------------------------
|
||||
void GetSurfaceInfo(
|
||||
HRESULT GetSurfaceInfo(
|
||||
_In_ size_t width,
|
||||
_In_ size_t height,
|
||||
_In_ DXGI_FORMAT fmt,
|
||||
_Out_opt_ size_t* outNumBytes,
|
||||
_Out_opt_ size_t* outRowBytes,
|
||||
_Out_opt_ size_t* outNumRows )
|
||||
_Out_opt_ size_t* outNumRows)
|
||||
{
|
||||
size_t numBytes = 0;
|
||||
size_t rowBytes = 0;
|
||||
size_t numRows = 0;
|
||||
uint64_t numBytes = 0;
|
||||
uint64_t rowBytes = 0;
|
||||
uint64_t numRows = 0;
|
||||
|
||||
bool bc = false;
|
||||
bool packed = false;
|
||||
@ -458,7 +461,7 @@ namespace
|
||||
case DXGI_FORMAT_BC4_TYPELESS:
|
||||
case DXGI_FORMAT_BC4_UNORM:
|
||||
case DXGI_FORMAT_BC4_SNORM:
|
||||
bc=true;
|
||||
bc = true;
|
||||
bpe = 8;
|
||||
break;
|
||||
|
||||
@ -496,6 +499,7 @@ namespace
|
||||
|
||||
case DXGI_FORMAT_NV12:
|
||||
case DXGI_FORMAT_420_OPAQUE:
|
||||
case DXGI_FORMAT_P208:
|
||||
planar = true;
|
||||
bpe = 2;
|
||||
break;
|
||||
@ -505,19 +509,22 @@ namespace
|
||||
planar = true;
|
||||
bpe = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bc)
|
||||
{
|
||||
size_t numBlocksWide = 0;
|
||||
uint64_t numBlocksWide = 0;
|
||||
if (width > 0)
|
||||
{
|
||||
numBlocksWide = std::max<size_t>( 1, (width + 3) / 4 );
|
||||
numBlocksWide = std::max<uint64_t>(1u, (uint64_t(width) + 3u) / 4u);
|
||||
}
|
||||
size_t numBlocksHigh = 0;
|
||||
uint64_t numBlocksHigh = 0;
|
||||
if (height > 0)
|
||||
{
|
||||
numBlocksHigh = std::max<size_t>( 1, (height + 3) / 4 );
|
||||
numBlocksHigh = std::max<uint64_t>(1u, (uint64_t(height) + 3u) / 4u);
|
||||
}
|
||||
rowBytes = numBlocksWide * bpe;
|
||||
numRows = numBlocksHigh;
|
||||
@ -525,42 +532,55 @@ namespace
|
||||
}
|
||||
else if (packed)
|
||||
{
|
||||
rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
|
||||
numRows = height;
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
else if ( fmt == DXGI_FORMAT_NV11 )
|
||||
else if (fmt == DXGI_FORMAT_NV11)
|
||||
{
|
||||
rowBytes = ( ( width + 3 ) >> 2 ) * 4;
|
||||
numRows = height * 2; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
rowBytes = ((uint64_t(width) + 3u) >> 2) * 4u;
|
||||
numRows = uint64_t(height) * 2u; // Direct3D makes this simplifying assumption, although it is larger than the 4:1:1 data
|
||||
numBytes = rowBytes * numRows;
|
||||
}
|
||||
else if (planar)
|
||||
{
|
||||
rowBytes = ( ( width + 1 ) >> 1 ) * bpe;
|
||||
numBytes = ( rowBytes * height ) + ( ( rowBytes * height + 1 ) >> 1 );
|
||||
numRows = height + ( ( height + 1 ) >> 1 );
|
||||
rowBytes = ((uint64_t(width) + 1u) >> 1) * bpe;
|
||||
numBytes = (rowBytes * uint64_t(height)) + ((rowBytes * uint64_t(height) + 1u) >> 1);
|
||||
numRows = height + ((uint64_t(height) + 1u) >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bpp = BitsPerPixel( fmt );
|
||||
rowBytes = ( width * bpp + 7 ) / 8; // round up to nearest byte
|
||||
numRows = height;
|
||||
size_t bpp = BitsPerPixel(fmt);
|
||||
if (!bpp)
|
||||
return E_INVALIDARG;
|
||||
|
||||
rowBytes = (uint64_t(width) * bpp + 7u) / 8u; // round up to nearest byte
|
||||
numRows = uint64_t(height);
|
||||
numBytes = rowBytes * height;
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_ARM) || defined(_M_HYBRID_X86_ARM64)
|
||||
static_assert(sizeof(size_t) == 4, "Not a 32-bit platform!");
|
||||
if (numBytes > UINT32_MAX || rowBytes > UINT32_MAX || numRows > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
#else
|
||||
static_assert(sizeof(size_t) == 8, "Not a 64-bit platform!");
|
||||
#endif
|
||||
|
||||
if (outNumBytes)
|
||||
{
|
||||
*outNumBytes = numBytes;
|
||||
*outNumBytes = static_cast<size_t>(numBytes);
|
||||
}
|
||||
if (outRowBytes)
|
||||
{
|
||||
*outRowBytes = rowBytes;
|
||||
*outRowBytes = static_cast<size_t>(rowBytes);
|
||||
}
|
||||
if (outNumRows)
|
||||
{
|
||||
*outNumRows = numRows;
|
||||
*outNumRows = static_cast<size_t>(numRows);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -934,7 +954,9 @@ HRESULT DirectX::SaveDDSTextureToFile(
|
||||
}
|
||||
|
||||
size_t rowPitch, slicePitch, rowCount;
|
||||
GetSurfaceInfo(static_cast<size_t>(desc.Width), desc.Height, desc.Format, &slicePitch, &rowPitch, &rowCount);
|
||||
hr = GetSurfaceInfo(static_cast<size_t>(desc.Width), desc.Height, desc.Format, &slicePitch, &rowPitch, &rowCount);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (rowPitch > UINT32_MAX || slicePitch > UINT32_MAX)
|
||||
return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
|
||||
|
Loading…
Reference in New Issue
Block a user