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

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

View File

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