ComputePitch now returns an HRESULT (#113)

This commit is contained in:
Chuck Walbourn
2018-08-03 16:49:30 -07:00
committed by GitHub
parent 3f8b8d36b9
commit 114a0acf6b
11 changed files with 379 additions and 183 deletions

View File

@@ -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);

View File

@@ -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);