1
0
mirror of https://github.com/microsoft/DirectXTex synced 2024-11-21 20:10:05 +00:00

General code cleanuP

This commit is contained in:
Chuck Walbourn 2016-09-08 19:09:46 -07:00
parent 53e66ba1e9
commit 51bc3d5b16
28 changed files with 13052 additions and 12638 deletions

View File

@ -165,21 +165,11 @@ namespace
}
// open the file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName,
GENERIC_READ,
FILE_SHARE_READ,
OPEN_EXISTING,
nullptr ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName,
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr ) ) );
#endif
if ( !hFile )
{

View File

@ -21,32 +21,32 @@
#include "BC.h"
using namespace DirectX;
using namespace DirectX::PackedVector;
namespace DirectX
namespace
{
//-------------------------------------------------------------------------------------
// Constants
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
// Constants
//-------------------------------------------------------------------------------------
// Perceptual weightings for the importance of each channel.
const HDRColorA g_Luminance(0.2125f / 0.7154f, 1.0f, 0.0721f / 0.7154f, 1.0f);
const HDRColorA g_LuminanceInv(0.7154f / 0.2125f, 1.0f, 0.7154f / 0.0721f, 1.0f);
// Perceptual weightings for the importance of each channel.
static const HDRColorA g_Luminance (0.2125f / 0.7154f, 1.0f, 0.0721f / 0.7154f, 1.0f);
static const HDRColorA g_LuminanceInv(0.7154f / 0.2125f, 1.0f, 0.7154f / 0.0721f, 1.0f);
//-------------------------------------------------------------------------------------
// Decode/Encode RGB 5/6/5 colors
//-------------------------------------------------------------------------------------
inline static void Decode565(_Out_ HDRColorA *pColor, _In_ const uint16_t w565)
{
pColor->r = (float) ((w565 >> 11) & 31) * (1.0f / 31.0f);
pColor->g = (float) ((w565 >> 5) & 63) * (1.0f / 63.0f);
pColor->b = (float) ((w565 >> 0) & 31) * (1.0f / 31.0f);
//-------------------------------------------------------------------------------------
// Decode/Encode RGB 5/6/5 colors
//-------------------------------------------------------------------------------------
inline void Decode565(_Out_ HDRColorA *pColor, _In_ const uint16_t w565)
{
pColor->r = (float)((w565 >> 11) & 31) * (1.0f / 31.0f);
pColor->g = (float)((w565 >> 5) & 63) * (1.0f / 63.0f);
pColor->b = (float)((w565 >> 0) & 31) * (1.0f / 31.0f);
pColor->a = 1.0f;
}
}
inline static uint16_t Encode565(_In_ const HDRColorA *pColor)
{
inline uint16_t Encode565(_In_ const HDRColorA *pColor)
{
HDRColorA Color;
Color.r = (pColor->r < 0.0f) ? 0.0f : (pColor->r > 1.0f) ? 1.0f : pColor->r;
@ -55,23 +55,27 @@ inline static uint16_t Encode565(_In_ const HDRColorA *pColor)
uint16_t w;
w = (uint16_t) ((static_cast<int32_t>(Color.r * 31.0f + 0.5f) << 11) |
w = (uint16_t)((static_cast<int32_t>(Color.r * 31.0f + 0.5f) << 11) |
(static_cast<int32_t>(Color.g * 63.0f + 0.5f) << 5) |
(static_cast<int32_t>(Color.b * 31.0f + 0.5f) << 0));
return w;
}
}
//-------------------------------------------------------------------------------------
static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pPoints, _In_ size_t cSteps, _In_ DWORD flags)
{
//-------------------------------------------------------------------------------------
void OptimizeRGB(
_Out_ HDRColorA *pX,
_Out_ HDRColorA *pY,
_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pPoints,
size_t cSteps,
DWORD flags)
{
static const float fEpsilon = (0.25f / 64.0f) * (0.25f / 64.0f);
static const float pC3[] = { 2.0f/2.0f, 1.0f/2.0f, 0.0f/2.0f };
static const float pD3[] = { 0.0f/2.0f, 1.0f/2.0f, 2.0f/2.0f };
static const float pC4[] = { 3.0f/3.0f, 2.0f/3.0f, 1.0f/3.0f, 0.0f/3.0f };
static const float pD4[] = { 0.0f/3.0f, 1.0f/3.0f, 2.0f/3.0f, 3.0f/3.0f };
static const float pC3[] = { 2.0f / 2.0f, 1.0f / 2.0f, 0.0f / 2.0f };
static const float pD3[] = { 0.0f / 2.0f, 1.0f / 2.0f, 2.0f / 2.0f };
static const float pC4[] = { 3.0f / 3.0f, 2.0f / 3.0f, 1.0f / 3.0f, 0.0f / 3.0f };
static const float pD4[] = { 0.0f / 3.0f, 1.0f / 3.0f, 2.0f / 3.0f, 3.0f / 3.0f };
const float *pC = (3 == cSteps) ? pC3 : pC4;
const float *pD = (3 == cSteps) ? pD3 : pD4;
@ -80,28 +84,28 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
HDRColorA X = (flags & BC_FLAGS_UNIFORM) ? HDRColorA(1.f, 1.f, 1.f, 1.f) : g_Luminance;
HDRColorA Y = HDRColorA(0.0f, 0.0f, 0.0f, 1.0f);
for(size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
{
#ifdef COLOR_WEIGHTS
if(pPoints[iPoint].a > 0.0f)
if (pPoints[iPoint].a > 0.0f)
#endif // COLOR_WEIGHTS
{
if(pPoints[iPoint].r < X.r)
if (pPoints[iPoint].r < X.r)
X.r = pPoints[iPoint].r;
if(pPoints[iPoint].g < X.g)
if (pPoints[iPoint].g < X.g)
X.g = pPoints[iPoint].g;
if(pPoints[iPoint].b < X.b)
if (pPoints[iPoint].b < X.b)
X.b = pPoints[iPoint].b;
if(pPoints[iPoint].r > Y.r)
if (pPoints[iPoint].r > Y.r)
Y.r = pPoints[iPoint].r;
if(pPoints[iPoint].g > Y.g)
if (pPoints[iPoint].g > Y.g)
Y.g = pPoints[iPoint].g;
if(pPoints[iPoint].b > Y.b)
if (pPoints[iPoint].b > Y.b)
Y.b = pPoints[iPoint].b;
}
}
@ -116,7 +120,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
float fAB = AB.r * AB.r + AB.g * AB.g + AB.b * AB.b;
// Single color block.. no need to root-find
if(fAB < FLT_MIN)
if (fAB < FLT_MIN)
{
pX->r = X.r; pX->g = X.g; pX->b = X.b;
pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
@ -140,7 +144,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
fDir[0] = fDir[1] = fDir[2] = fDir[3] = 0.0f;
for(size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
{
HDRColorA Pt;
Pt.r = (pPoints[iPoint].r - Mid.r) * Dir.r;
@ -179,44 +183,43 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
float fDirMax = fDir[0];
size_t iDirMax = 0;
for(size_t iDir = 1; iDir < 4; iDir++)
for (size_t iDir = 1; iDir < 4; iDir++)
{
if(fDir[iDir] > fDirMax)
if (fDir[iDir] > fDirMax)
{
fDirMax = fDir[iDir];
iDirMax = iDir;
}
}
if(iDirMax & 2)
if (iDirMax & 2)
{
float f = X.g; X.g = Y.g; Y.g = f;
}
if(iDirMax & 1)
if (iDirMax & 1)
{
float f = X.b; X.b = Y.b; Y.b = f;
}
// Two color block.. no need to root-find
if(fAB < 1.0f / 4096.0f)
if (fAB < 1.0f / 4096.0f)
{
pX->r = X.r; pX->g = X.g; pX->b = X.b;
pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
return;
}
// Use Newton's Method to find local minima of sum-of-squares error.
float fSteps = (float) (cSteps - 1);
float fSteps = (float)(cSteps - 1);
for(size_t iIteration = 0; iIteration < 8; iIteration++)
for (size_t iIteration = 0; iIteration < 8; iIteration++)
{
// Calculate new steps
HDRColorA pSteps[4];
for(size_t iStep = 0; iStep < cSteps; iStep++)
for (size_t iStep = 0; iStep < cSteps; iStep++)
{
pSteps[iStep].r = X.r * pC[iStep] + Y.r * pD[iStep];
pSteps[iStep].g = X.g * pC[iStep] + Y.g * pD[iStep];
@ -231,7 +234,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
float fLen = (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b);
if(fLen < (1.0f / 4096.0f))
if (fLen < (1.0f / 4096.0f))
break;
float fScale = fSteps / fLen;
@ -246,7 +249,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
HDRColorA dX, dY;
d2X = d2Y = dX.r = dX.g = dX.b = dY.r = dY.g = dY.b = 0.0f;
for(size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
for (size_t iPoint = 0; iPoint < NUM_PIXELS_PER_BLOCK; iPoint++)
{
float fDot = (pPoints[iPoint].r - X.r) * Dir.r +
(pPoints[iPoint].g - X.g) * Dir.g +
@ -254,9 +257,9 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
size_t iStep;
if(fDot <= 0.0f)
if (fDot <= 0.0f)
iStep = 0;
else if(fDot >= fSteps)
else if (fDot >= fSteps)
iStep = cSteps - 1;
else
iStep = static_cast<size_t>(fDot + 0.5f);
@ -286,9 +289,8 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
dY.b += fD * Diff.b;
}
// Move endpoints
if(d2X > 0.0f)
if (d2X > 0.0f)
{
float f = -1.0f / d2X;
@ -297,7 +299,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
X.b += dX.b * f;
}
if(d2Y > 0.0f)
if (d2Y > 0.0f)
{
float f = -1.0f / d2Y;
@ -306,7 +308,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
Y.b += dY.b * f;
}
if((dX.r * dX.r < fEpsilon) && (dX.g * dX.g < fEpsilon) && (dX.b * dX.b < fEpsilon) &&
if ((dX.r * dX.r < fEpsilon) && (dX.g * dX.g < fEpsilon) && (dX.b * dX.b < fEpsilon) &&
(dY.r * dY.r < fEpsilon) && (dY.g * dY.g < fEpsilon) && (dY.b * dY.b < fEpsilon))
{
break;
@ -315,46 +317,49 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
pX->r = X.r; pX->g = X.g; pX->b = X.b;
pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
}
}
//-------------------------------------------------------------------------------------
inline static void DecodeBC1( _Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_ const D3DX_BC1 *pBC, _In_ bool isbc1 )
{
assert( pColor && pBC );
static_assert( sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes" );
//-------------------------------------------------------------------------------------
inline void DecodeBC1(
_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor,
_In_ const D3DX_BC1 *pBC,
bool isbc1)
{
assert(pColor && pBC);
static_assert(sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes");
static XMVECTORF32 s_Scale = { 1.f/31.f, 1.f/63.f, 1.f/31.f, 1.f };
static XMVECTORF32 s_Scale = { 1.f / 31.f, 1.f / 63.f, 1.f / 31.f, 1.f };
XMVECTOR clr0 = XMLoadU565( reinterpret_cast<const XMU565*>(&pBC->rgb[0]) );
XMVECTOR clr1 = XMLoadU565( reinterpret_cast<const XMU565*>(&pBC->rgb[1]) );
XMVECTOR clr0 = XMLoadU565(reinterpret_cast<const XMU565*>(&pBC->rgb[0]));
XMVECTOR clr1 = XMLoadU565(reinterpret_cast<const XMU565*>(&pBC->rgb[1]));
clr0 = XMVectorMultiply( clr0, s_Scale );
clr1 = XMVectorMultiply( clr1, s_Scale );
clr0 = XMVectorMultiply(clr0, s_Scale);
clr1 = XMVectorMultiply(clr1, s_Scale);
clr0 = XMVectorSwizzle<2, 1, 0, 3>( clr0 );
clr1 = XMVectorSwizzle<2, 1, 0, 3>( clr1 );
clr0 = XMVectorSwizzle<2, 1, 0, 3>(clr0);
clr1 = XMVectorSwizzle<2, 1, 0, 3>(clr1);
clr0 = XMVectorSelect( g_XMIdentityR3, clr0, g_XMSelect1110 );
clr1 = XMVectorSelect( g_XMIdentityR3, clr1, g_XMSelect1110 );
clr0 = XMVectorSelect(g_XMIdentityR3, clr0, g_XMSelect1110);
clr1 = XMVectorSelect(g_XMIdentityR3, clr1, g_XMSelect1110);
XMVECTOR clr2, clr3;
if ( isbc1 && (pBC->rgb[0] <= pBC->rgb[1]) )
if (isbc1 && (pBC->rgb[0] <= pBC->rgb[1]))
{
clr2 = XMVectorLerp( clr0, clr1, 0.5f );
clr2 = XMVectorLerp(clr0, clr1, 0.5f);
clr3 = XMVectorZero(); // Alpha of 0
}
else
{
clr2 = XMVectorLerp( clr0, clr1, 1.f/3.f );
clr3 = XMVectorLerp( clr0, clr1, 2.f/3.f );
clr2 = XMVectorLerp(clr0, clr1, 1.f / 3.f);
clr3 = XMVectorLerp(clr0, clr1, 2.f / 3.f);
}
uint32_t dw = pBC->bitmap;
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 2)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 2)
{
switch(dw & 3)
switch (dw & 3)
{
case 0: pColor[i] = clr0; break;
case 1: pColor[i] = clr1; break;
@ -364,16 +369,19 @@ inline static void DecodeBC1( _Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColo
default: pColor[i] = clr3; break;
}
}
}
}
//-------------------------------------------------------------------------------------
static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor,
_In_ bool bColorKey, _In_ float alphaRef, _In_ DWORD flags)
{
assert( pBC && pColor );
static_assert( sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes" );
//-------------------------------------------------------------------------------------
void EncodeBC1(
_Out_ D3DX_BC1 *pBC,
_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor,
bool bColorKey,
float alphaRef,
DWORD flags)
{
assert(pBC && pColor);
static_assert(sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes");
// Determine if we need to colorkey this block
size_t uSteps;
@ -382,13 +390,13 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
{
size_t uColorKey = 0;
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
if(pColor[i].a < alphaRef)
if (pColor[i].a < alphaRef)
uColorKey++;
}
if(NUM_PIXELS_PER_BLOCK == uColorKey)
if (NUM_PIXELS_PER_BLOCK == uColorKey)
{
pBC->rgb[0] = 0x0000;
pBC->rgb[1] = 0xffff;
@ -413,7 +421,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
memset(Error, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(HDRColorA));
size_t i;
for(i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
HDRColorA Clr;
Clr.r = pColor[i].r;
@ -444,18 +452,18 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
Diff.g = Color[i].a * (Clr.g - Color[i].g);
Diff.b = Color[i].a * (Clr.b - Color[i].b);
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 15 );
_Analysis_assume_( i < 15 );
assert(i < 15);
_Analysis_assume_(i < 15);
Error[i + 1].r += Diff.r * (7.0f / 16.0f);
Error[i + 1].g += Diff.g * (7.0f / 16.0f);
Error[i + 1].b += Diff.b * (7.0f / 16.0f);
}
if(i < 12)
if (i < 12)
{
if(i & 3)
if (i & 3)
{
Error[i + 3].r += Diff.r * (3.0f / 16.0f);
Error[i + 3].g += Diff.g * (3.0f / 16.0f);
@ -466,10 +474,10 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
Error[i + 4].g += Diff.g * (5.0f / 16.0f);
Error[i + 4].b += Diff.b * (5.0f / 16.0f);
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 11 );
_Analysis_assume_( i < 11 );
assert(i < 11);
_Analysis_assume_(i < 11);
Error[i + 5].r += Diff.r * (1.0f / 16.0f);
Error[i + 5].g += Diff.g * (1.0f / 16.0f);
Error[i + 5].b += Diff.b * (1.0f / 16.0f);
@ -477,7 +485,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
}
}
if ( !( flags & BC_FLAGS_UNIFORM ) )
if (!(flags & BC_FLAGS_UNIFORM))
{
Color[i].r *= g_Luminance.r;
Color[i].g *= g_Luminance.g;
@ -491,7 +499,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
OptimizeRGB(&ColorA, &ColorB, Color, uSteps, flags);
if ( flags & BC_FLAGS_UNIFORM )
if (flags & BC_FLAGS_UNIFORM)
{
ColorC = ColorA;
ColorD = ColorB;
@ -510,7 +518,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
uint16_t wColorA = Encode565(&ColorC);
uint16_t wColorB = Encode565(&ColorD);
if((uSteps == 4) && (wColorA == wColorB))
if ((uSteps == 4) && (wColorA == wColorB))
{
pBC->rgb[0] = wColorA;
pBC->rgb[1] = wColorB;
@ -521,7 +529,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
Decode565(&ColorC, wColorA);
Decode565(&ColorD, wColorB);
if ( flags & BC_FLAGS_UNIFORM )
if (flags & BC_FLAGS_UNIFORM)
{
ColorA = ColorC;
ColorB = ColorD;
@ -540,7 +548,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
// Calculate color steps
HDRColorA Step[4];
if((3 == uSteps) == (wColorA <= wColorB))
if ((3 == uSteps) == (wColorA <= wColorB))
{
pBC->rgb[0] = wColorA;
pBC->rgb[1] = wColorB;
@ -561,7 +569,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
static const size_t pSteps4[] = { 0, 2, 3, 1 };
const size_t *pSteps;
if(3 == uSteps)
if (3 == uSteps)
{
pSteps = pSteps3;
@ -582,7 +590,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
Dir.g = Step[1].g - Step[0].g;
Dir.b = Step[1].b - Step[0].b;
float fSteps = (float) (uSteps - 1);
float fSteps = (float)(uSteps - 1);
float fScale = (wColorA != wColorB) ? (fSteps / (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b)) : 0.0f;
Dir.r *= fScale;
@ -594,16 +602,16 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
if (flags & BC_FLAGS_DITHER_RGB)
memset(Error, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(HDRColorA));
for(i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
if((3 == uSteps) && (pColor[i].a < alphaRef))
if ((3 == uSteps) && (pColor[i].a < alphaRef))
{
dw = (3 << 30) | (dw >> 2);
}
else
{
HDRColorA Clr;
if ( flags & BC_FLAGS_UNIFORM )
if (flags & BC_FLAGS_UNIFORM)
{
Clr.r = pColor[i].r;
Clr.g = pColor[i].g;
@ -626,12 +634,12 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
float fDot = (Clr.r - Step[0].r) * Dir.r + (Clr.g - Step[0].g) * Dir.g + (Clr.b - Step[0].b) * Dir.b;
uint32_t iStep;
if(fDot <= 0.0f)
if (fDot <= 0.0f)
iStep = 0;
else if(fDot >= fSteps)
else if (fDot >= fSteps)
iStep = 1;
else
iStep = static_cast<uint32_t>( pSteps[static_cast<size_t>(fDot + 0.5f)] );
iStep = static_cast<uint32_t>(pSteps[static_cast<size_t>(fDot + 0.5f)]);
dw = (iStep << 30) | (dw >> 2);
@ -642,16 +650,16 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
Diff.g = Color[i].a * (Clr.g - Step[iStep].g);
Diff.b = Color[i].a * (Clr.b - Step[iStep].b);
if(3 != (i & 3))
if (3 != (i & 3))
{
Error[i + 1].r += Diff.r * (7.0f / 16.0f);
Error[i + 1].g += Diff.g * (7.0f / 16.0f);
Error[i + 1].b += Diff.b * (7.0f / 16.0f);
}
if(i < 12)
if (i < 12)
{
if(i & 3)
if (i & 3)
{
Error[i + 3].r += Diff.r * (3.0f / 16.0f);
Error[i + 3].g += Diff.g * (3.0f / 16.0f);
@ -662,7 +670,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
Error[i + 4].g += Diff.g * (5.0f / 16.0f);
Error[i + 4].b += Diff.b * (5.0f / 16.0f);
if(3 != (i & 3))
if (3 != (i & 3))
{
Error[i + 5].r += Diff.r * (1.0f / 16.0f);
Error[i + 5].g += Diff.g * (1.0f / 16.0f);
@ -674,12 +682,12 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
}
pBC->bitmap = dw;
}
}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
#ifdef COLOR_WEIGHTS
static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor)
{
void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor)
{
#ifdef COLOR_AVG_0WEIGHTS
// Compute avg color
HDRColorA Color;
@ -687,7 +695,7 @@ static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK)
Color.g = pColor[0].g;
Color.b = pColor[0].b;
for(size_t i = 1; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 1; i < NUM_PIXELS_PER_BLOCK; ++i)
{
Color.r += pColor[i].r;
Color.g += pColor[i].g;
@ -707,8 +715,9 @@ static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK)
pBC->rgb[0] = wColor;
pBC->rgb[1] = wColor;
pBC->bitmap = 0x00000000;
}
}
#endif // COLOR_WEIGHTS
}
//=====================================================================================
@ -719,16 +728,16 @@ static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK)
// BC1 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC1(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC1(XMVECTOR *pColor, const uint8_t *pBC)
{
auto pBC1 = reinterpret_cast<const D3DX_BC1 *>(pBC);
DecodeBC1( pColor, pBC1, true );
DecodeBC1(pColor, pBC1, true);
}
_Use_decl_annotations_
void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD flags)
void DirectX::D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD flags)
{
assert( pBC && pColor );
assert(pBC && pColor);
HDRColorA Color[NUM_PIXELS_PER_BLOCK];
@ -737,10 +746,10 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
float fError[NUM_PIXELS_PER_BLOCK];
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
HDRColorA clr;
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( &clr ), pColor[i] );
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(&clr), pColor[i]);
float fAlph = clr.a + fError[i];
@ -751,24 +760,24 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
float fDiff = fAlph - Color[i].a;
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 15 );
_Analysis_assume_( i < 15 );
assert(i < 15);
_Analysis_assume_(i < 15);
fError[i + 1] += fDiff * (7.0f / 16.0f);
}
if(i < 12)
if (i < 12)
{
if(i & 3)
if (i & 3)
fError[i + 3] += fDiff * (3.0f / 16.0f);
fError[i + 4] += fDiff * (5.0f / 16.0f);
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 11 );
_Analysis_assume_( i < 11 );
assert(i < 11);
_Analysis_assume_(i < 11);
fError[i + 5] += fDiff * (1.0f / 16.0f);
}
}
@ -776,9 +785,9 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
}
else
{
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( &Color[i] ), pColor[i] );
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(&Color[i]), pColor[i]);
}
}
@ -791,10 +800,10 @@ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD f
// BC2 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes" );
assert(pColor && pBC);
static_assert(sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes");
auto pBC2 = reinterpret_cast<const D3DX_BC2 *>(pBC);
@ -804,28 +813,28 @@ void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
// 4-bit alpha part
DWORD dw = pBC2->bitmap[0];
for(size_t i = 0; i < 8; ++i, dw >>= 4)
for (size_t i = 0; i < 8; ++i, dw >>= 4)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSetW( pColor[i], (float) (dw & 0xf) * (1.0f / 15.0f) );
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSetW(pColor[i], (float)(dw & 0xf) * (1.0f / 15.0f));
}
dw = pBC2->bitmap[1];
for(size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 4)
pColor[i] = XMVectorSetW( pColor[i], (float) (dw & 0xf) * (1.0f / 15.0f) );
for (size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 4)
pColor[i] = XMVectorSetW(pColor[i], (float)(dw & 0xf) * (1.0f / 15.0f));
}
_Use_decl_annotations_
void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
void DirectX::D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
assert( pBC && pColor );
static_assert( sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes" );
assert(pBC && pColor);
static_assert(sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes");
HDRColorA Color[NUM_PIXELS_PER_BLOCK];
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( &Color[i] ), pColor[i] );
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(&Color[i]), pColor[i]);
}
auto pBC2 = reinterpret_cast<D3DX_BC2 *>(pBC);
@ -838,7 +847,7 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
if (flags & BC_FLAGS_DITHER_A)
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
float fAlph = Color[i].a;
if (flags & BC_FLAGS_DITHER_A)
@ -851,26 +860,26 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
if (flags & BC_FLAGS_DITHER_A)
{
float fDiff = fAlph - (float) u * (1.0f / 15.0f);
float fDiff = fAlph - (float)u * (1.0f / 15.0f);
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 15 );
_Analysis_assume_( i < 15 );
assert(i < 15);
_Analysis_assume_(i < 15);
fError[i + 1] += fDiff * (7.0f / 16.0f);
}
if(i < 12)
if (i < 12)
{
if(i & 3)
if (i & 3)
fError[i + 3] += fDiff * (3.0f / 16.0f);
fError[i + 4] += fDiff * (5.0f / 16.0f);
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 11 );
_Analysis_assume_( i < 11 );
assert(i < 11);
_Analysis_assume_(i < 11);
fError[i + 5] += fDiff * (1.0f / 16.0f);
}
}
@ -879,7 +888,7 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
// RGB part
#ifdef COLOR_WEIGHTS
if(!pBC2->bitmap[0] && !pBC2->bitmap[1])
if (!pBC2->bitmap[0] && !pBC2->bitmap[1])
{
EncodeSolidBC1(pBC2->dxt1, Color);
return;
@ -894,10 +903,10 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
// BC3 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes" );
assert(pColor && pBC);
static_assert(sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes");
auto pBC3 = reinterpret_cast<const D3DX_BC3 *>(pBC);
@ -907,17 +916,17 @@ void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
// Adaptive 3-bit alpha part
float fAlpha[8];
fAlpha[0] = ((float) pBC3->alpha[0]) * (1.0f / 255.0f);
fAlpha[1] = ((float) pBC3->alpha[1]) * (1.0f / 255.0f);
fAlpha[0] = ((float)pBC3->alpha[0]) * (1.0f / 255.0f);
fAlpha[1] = ((float)pBC3->alpha[1]) * (1.0f / 255.0f);
if(pBC3->alpha[0] > pBC3->alpha[1])
if (pBC3->alpha[0] > pBC3->alpha[1])
{
for(size_t i = 1; i < 7; ++i)
for (size_t i = 1; i < 7; ++i)
fAlpha[i + 1] = (fAlpha[0] * (7 - i) + fAlpha[1] * i) * (1.0f / 7.0f);
}
else
{
for(size_t i = 1; i < 5; ++i)
for (size_t i = 1; i < 5; ++i)
fAlpha[i + 1] = (fAlpha[0] * (5 - i) + fAlpha[1] * i) * (1.0f / 5.0f);
fAlpha[6] = 0.0f;
@ -926,25 +935,25 @@ void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
DWORD dw = pBC3->bitmap[0] | (pBC3->bitmap[1] << 8) | (pBC3->bitmap[2] << 16);
for(size_t i = 0; i < 8; ++i, dw >>= 3)
pColor[i] = XMVectorSetW( pColor[i], fAlpha[dw & 0x7] );
for (size_t i = 0; i < 8; ++i, dw >>= 3)
pColor[i] = XMVectorSetW(pColor[i], fAlpha[dw & 0x7]);
dw = pBC3->bitmap[3] | (pBC3->bitmap[4] << 8) | (pBC3->bitmap[5] << 16);
for(size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 3)
pColor[i] = XMVectorSetW( pColor[i], fAlpha[dw & 0x7] );
for (size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 3)
pColor[i] = XMVectorSetW(pColor[i], fAlpha[dw & 0x7]);
}
_Use_decl_annotations_
void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
void DirectX::D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
assert( pBC && pColor );
static_assert( sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes" );
assert(pBC && pColor);
static_assert(sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes");
HDRColorA Color[NUM_PIXELS_PER_BLOCK];
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( &Color[i] ), pColor[i] );
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(&Color[i]), pColor[i]);
}
auto pBC3 = reinterpret_cast<D3DX_BC3 *>(pBC);
@ -961,7 +970,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
if (flags & BC_FLAGS_DITHER_A)
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
for(size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
float fAlph = Color[i].a;
if (flags & BC_FLAGS_DITHER_A)
@ -969,33 +978,33 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
fAlpha[i] = static_cast<int32_t>(fAlph * 255.0f + 0.5f) * (1.0f / 255.0f);
if(fAlpha[i] < fMinAlpha)
if (fAlpha[i] < fMinAlpha)
fMinAlpha = fAlpha[i];
else if(fAlpha[i] > fMaxAlpha)
else if (fAlpha[i] > fMaxAlpha)
fMaxAlpha = fAlpha[i];
if (flags & BC_FLAGS_DITHER_A)
{
float fDiff = fAlph - fAlpha[i];
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 15 );
_Analysis_assume_( i < 15 );
assert(i < 15);
_Analysis_assume_(i < 15);
fError[i + 1] += fDiff * (7.0f / 16.0f);
}
if(i < 12)
if (i < 12)
{
if(i & 3)
if (i & 3)
fError[i + 3] += fDiff * (3.0f / 16.0f);
fError[i + 4] += fDiff * (5.0f / 16.0f);
if(3 != (i & 3))
if (3 != (i & 3))
{
assert( i < 11 );
_Analysis_assume_( i < 11 );
assert(i < 11);
_Analysis_assume_(i < 11);
fError[i + 5] += fDiff * (1.0f / 16.0f);
}
}
@ -1003,7 +1012,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
}
#ifdef COLOR_WEIGHTS
if(0.0f == fMaxAlpha)
if (0.0f == fMaxAlpha)
{
EncodeSolidBC1(&pBC3->dxt1, Color);
pBC3->alpha[0] = 0x00;
@ -1016,7 +1025,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
EncodeBC1(&pBC3->bc1, Color, false, 0.f, flags);
// Alpha part
if(1.0f == fMinAlpha)
if (1.0f == fMinAlpha)
{
pBC3->alpha[0] = 0xff;
pBC3->alpha[1] = 0xff;
@ -1033,11 +1042,11 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
uint8_t bAlphaA = (uint8_t) static_cast<int32_t>(fAlphaA * 255.0f + 0.5f);
uint8_t bAlphaB = (uint8_t) static_cast<int32_t>(fAlphaB * 255.0f + 0.5f);
fAlphaA = (float) bAlphaA * (1.0f / 255.0f);
fAlphaB = (float) bAlphaB * (1.0f / 255.0f);
fAlphaA = (float)bAlphaA * (1.0f / 255.0f);
fAlphaB = (float)bAlphaB * (1.0f / 255.0f);
// Setup block
if((8 == uSteps) && (bAlphaA == bAlphaB))
if ((8 == uSteps) && (bAlphaA == bAlphaB))
{
pBC3->alpha[0] = bAlphaA;
pBC3->alpha[1] = bAlphaB;
@ -1051,7 +1060,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
const size_t *pSteps;
float fStep[8];
if(6 == uSteps)
if (6 == uSteps)
{
pBC3->alpha[0] = bAlphaA;
pBC3->alpha[1] = bAlphaB;
@ -1059,7 +1068,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
fStep[0] = fAlphaA;
fStep[1] = fAlphaB;
for(size_t i = 1; i < 5; ++i)
for (size_t i = 1; i < 5; ++i)
fStep[i + 1] = (fStep[0] * (5 - i) + fStep[1] * i) * (1.0f / 5.0f);
fStep[6] = 0.0f;
@ -1075,27 +1084,27 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
fStep[0] = fAlphaB;
fStep[1] = fAlphaA;
for(size_t i = 1; i < 7; ++i)
for (size_t i = 1; i < 7; ++i)
fStep[i + 1] = (fStep[0] * (7 - i) + fStep[1] * i) * (1.0f / 7.0f);
pSteps = pSteps8;
}
// Encode alpha bitmap
float fSteps = (float) (uSteps - 1);
float fSteps = (float)(uSteps - 1);
float fScale = (fStep[0] != fStep[1]) ? (fSteps / (fStep[1] - fStep[0])) : 0.0f;
if (flags & BC_FLAGS_DITHER_A)
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
for(size_t iSet = 0; iSet < 2; iSet++)
for (size_t iSet = 0; iSet < 2; iSet++)
{
uint32_t dw = 0;
size_t iMin = iSet * 8;
size_t iLim = iMin + 8;
for(size_t i = iMin; i < iLim; ++i)
for (size_t i = iMin; i < iLim; ++i)
{
float fAlph = Color[i].a;
if (flags & BC_FLAGS_DITHER_A)
@ -1103,12 +1112,12 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
float fDot = (fAlph - fStep[0]) * fScale;
uint32_t iStep;
if(fDot <= 0.0f)
if (fDot <= 0.0f)
iStep = ((6 == uSteps) && (fAlph <= fStep[0] * 0.5f)) ? 6 : 0;
else if(fDot >= fSteps)
else if (fDot >= fSteps)
iStep = ((6 == uSteps) && (fAlph >= (fStep[1] + 1.0f) * 0.5f)) ? 7 : 1;
else
iStep = static_cast<uint32_t>( pSteps[static_cast<size_t>(fDot + 0.5f)] );
iStep = static_cast<uint32_t>(pSteps[static_cast<size_t>(fDot + 0.5f)]);
dw = (iStep << 21) | (dw >> 3);
@ -1116,26 +1125,24 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
float fDiff = (fAlph - fStep[iStep]);
if(3 != (i & 3))
if (3 != (i & 3))
fError[i + 1] += fDiff * (7.0f / 16.0f);
if(i < 12)
if (i < 12)
{
if(i & 3)
if (i & 3)
fError[i + 3] += fDiff * (3.0f / 16.0f);
fError[i + 4] += fDiff * (5.0f / 16.0f);
if(3 != (i & 3))
if (3 != (i & 3))
fError[i + 5] += fDiff * (1.0f / 16.0f);
}
}
}
pBC3->bitmap[0 + iSet * 3] = ((uint8_t *) &dw)[0];
pBC3->bitmap[1 + iSet * 3] = ((uint8_t *) &dw)[1];
pBC3->bitmap[2 + iSet * 3] = ((uint8_t *) &dw)[2];
pBC3->bitmap[0 + iSet * 3] = ((uint8_t *)&dw)[0];
pBC3->bitmap[1 + iSet * 3] = ((uint8_t *)&dw)[1];
pBC3->bitmap[2 + iSet * 3] = ((uint8_t *)&dw)[2];
}
}
} // namespace

View File

@ -17,8 +17,7 @@
#include "BC.h"
namespace DirectX
{
using namespace DirectX;
//------------------------------------------------------------------------------------
// Constants
@ -26,21 +25,23 @@ namespace DirectX
// Because these are used in SAL annotations, they need to remain macros rather than const values
#define BLOCK_LEN 4
// length of each block in texel
// length of each block in texel
#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN)
// total texels in a 4x4 block.
// total texels in a 4x4 block.
//------------------------------------------------------------------------------------
// Structures
//-------------------------------------------------------------------------------------
namespace
{
//------------------------------------------------------------------------------------
// Structures
//-------------------------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable : 4201)
// BC4U/BC5U
struct BC4_UNORM
{
// BC4U/BC5U
struct BC4_UNORM
{
float R(size_t uOffset) const
{
size_t uIndex = GetIndex(uOffset);
@ -58,7 +59,7 @@ struct BC4_UNORM
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
@ -67,19 +68,19 @@ struct BC4_UNORM
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
}
}
size_t GetIndex(size_t uOffset) const
{
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
data |= ((uint64_t) uIndex << (3*uOffset + 16));
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
}
union
@ -92,11 +93,11 @@ struct BC4_UNORM
};
uint64_t data;
};
};
};
// BC4S/BC5S
struct BC4_SNORM
{
// BC4S/BC5S
struct BC4_SNORM
{
float R(size_t uOffset) const
{
size_t uIndex = GetIndex(uOffset);
@ -105,8 +106,8 @@ struct BC4_SNORM
float DecodeFromIndex(size_t uIndex) const
{
int8_t sred_0 = (red_0 == -128)? -127 : red_0;
int8_t sred_1 = (red_1 == -128)? -127 : red_1;
int8_t sred_0 = (red_0 == -128) ? -127 : red_0;
int8_t sred_1 = (red_1 == -128) ? -127 : red_1;
if (uIndex == 0)
return sred_0 / 127.0f;
@ -117,7 +118,7 @@ struct BC4_SNORM
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
@ -126,19 +127,19 @@ struct BC4_SNORM
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
}
}
size_t GetIndex(size_t uOffset) const
{
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
data |= ((uint64_t) uIndex << (3*uOffset + 16));
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
}
union
@ -151,40 +152,43 @@ struct BC4_SNORM
};
uint64_t data;
};
};
};
#pragma warning(pop)
//-------------------------------------------------------------------------------------
// Convert a floating point value to an 8-bit SNORM
//-------------------------------------------------------------------------------------
static void inline FloatToSNorm( _In_ float fVal, _Out_ int8_t *piSNorm )
{
const uint32_t dwMostNeg = ( 1 << ( 8 * sizeof( int8_t ) - 1 ) );
//-------------------------------------------------------------------------------------
// Convert a floating point value to an 8-bit SNORM
//-------------------------------------------------------------------------------------
void inline FloatToSNorm(_In_ float fVal, _Out_ int8_t *piSNorm)
{
const uint32_t dwMostNeg = (1 << (8 * sizeof(int8_t) - 1));
if( _isnan( fVal ) )
if (_isnan(fVal))
fVal = 0;
else
if( fVal > 1 )
if (fVal > 1)
fVal = 1; // Clamp to 1
else
if( fVal < -1 )
if (fVal < -1)
fVal = -1; // Clamp to -1
fVal = fVal * (int8_t) ( dwMostNeg - 1 );
fVal = fVal * (int8_t)(dwMostNeg - 1);
if( fVal >= 0 )
if (fVal >= 0)
fVal += .5f;
else
fVal -= .5f;
*piSNorm = (int8_t) (fVal);
}
*piSNorm = (int8_t)(fVal);
}
//------------------------------------------------------------------------------
static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1)
{
//------------------------------------------------------------------------------
void FindEndPointsBC4U(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_Out_ uint8_t &endpointU_0,
_Out_ uint8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
@ -198,11 +202,11 @@ static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[],
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
if (theTexelsU[i]<fBlockMin)
if (theTexelsU[i] < fBlockMin)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i]>fBlockMax)
else if (theTexelsU[i] > fBlockMax)
{
fBlockMax = theTexelsU[i];
}
@ -210,7 +214,7 @@ static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[],
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
// Using Optimize
float fStart, fEnd;
@ -219,8 +223,8 @@ static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[],
{
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
iStart = (uint8_t) (fStart * 255.0f);
iEnd = (uint8_t) (fEnd * 255.0f);
iStart = (uint8_t)(fStart * 255.0f);
iEnd = (uint8_t)(fEnd * 255.0f);
endpointU_0 = iEnd;
endpointU_1 = iStart;
@ -229,16 +233,19 @@ static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[],
{
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
iStart = (uint8_t) (fStart * 255.0f);
iEnd = (uint8_t) (fEnd * 255.0f);
iStart = (uint8_t)(fStart * 255.0f);
iEnd = (uint8_t)(fEnd * 255.0f);
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
}
static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1)
{
void FindEndPointsBC4S(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_Out_ int8_t &endpointU_0,
_Out_ int8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
@ -252,11 +259,11 @@ static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
if (theTexelsU[i]<fBlockMin)
if (theTexelsU[i] < fBlockMin)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i]>fBlockMax)
else if (theTexelsU[i] > fBlockMax)
{
fBlockMax = theTexelsU[i];
}
@ -264,7 +271,7 @@ static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
// Using Optimize
float fStart, fEnd;
@ -289,30 +296,42 @@ static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
}
//------------------------------------------------------------------------------
static inline void FindEndPointsBC5U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1, _Out_ uint8_t &endpointV_0, _Out_ uint8_t &endpointV_1)
{
//------------------------------------------------------------------------------
inline void FindEndPointsBC5U(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ uint8_t &endpointU_0,
_Out_ uint8_t &endpointU_1,
_Out_ uint8_t &endpointV_0,
_Out_ uint8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4U( theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4U( theTexelsV, endpointV_0, endpointV_1);
}
FindEndPointsBC4U(theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4U(theTexelsV, endpointV_0, endpointV_1);
}
static inline void FindEndPointsBC5S( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1, _Out_ int8_t &endpointV_0, _Out_ int8_t &endpointV_1)
{
inline void FindEndPointsBC5S(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ int8_t &endpointU_0,
_Out_ int8_t &endpointU_1,
_Out_ int8_t &endpointV_0,
_Out_ int8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4S( theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4S( theTexelsV, endpointV_0, endpointV_1);
}
FindEndPointsBC4S(theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4S(theTexelsV, endpointV_0, endpointV_1);
}
//------------------------------------------------------------------------------
static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
//------------------------------------------------------------------------------
void FindClosestUNORM(
_Inout_ BC4_UNORM* pBC,
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
@ -325,7 +344,7 @@ static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
{
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
@ -334,10 +353,12 @@ static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
}
pBC->SetIndex(i, uBestIndex);
}
}
}
static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
void FindClosestSNORM(
_Inout_ BC4_SNORM* pBC,
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
@ -350,7 +371,7 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
{
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
@ -359,6 +380,7 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
}
pBC->SetIndex(i, uBestIndex);
}
}
}
@ -370,42 +392,42 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
// BC4 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC4U( XMVECTOR *pColor, const uint8_t *pBC )
void DirectX::D3DXDecodeBC4U(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC4U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
@ -413,7 +435,7 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
theTexelsU[i] = XMVectorGetX( pColor[i] );
theTexelsU[i] = XMVectorGetX(pColor[i]);
}
FindEndPointsBC4U(theTexelsU, pBC4->red_0, pBC4->red_1);
@ -421,12 +443,12 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
}
_Use_decl_annotations_
void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC4S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
@ -434,7 +456,7 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
theTexelsU[i] = XMVectorGetX( pColor[i] );
theTexelsU[i] = XMVectorGetX(pColor[i]);
}
FindEndPointsBC4S(theTexelsU, pBC4->red_0, pBC4->red_1);
@ -446,55 +468,55 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
// BC5 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
auto pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
auto pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC5U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM)*2);
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
auto pBCR = reinterpret_cast<BC4_UNORM*>(pBC);
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMFLOAT4A clr;
XMStoreFloat4A( &clr, pColor[i] );
XMStoreFloat4A(&clr, pColor[i]);
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
@ -512,23 +534,23 @@ void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
}
_Use_decl_annotations_
void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC5S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM)*2);
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
auto pBCR = reinterpret_cast<BC4_SNORM*>(pBC);
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMFLOAT4A clr;
XMStoreFloat4A( &clr, pColor[i] );
XMStoreFloat4A(&clr, pColor[i]);
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
@ -544,5 +566,3 @@ void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
FindClosestSNORM(pBCR, theTexelsU);
FindClosestSNORM(pBCG, theTexelsV);
}
} // namespace

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@
#pragma comment(lib,"dxguid.lib")
#endif
using namespace DirectX;
using Microsoft::WRL::ComPtr;
namespace
@ -82,9 +83,6 @@ namespace
}
};
namespace DirectX
{
GPUCompressBC::GPUCompressBC() :
m_bcformat(DXGI_FORMAT_UNKNOWN),
m_srcformat(DXGI_FORMAT_UNKNOWN),
@ -97,79 +95,79 @@ GPUCompressBC::GPUCompressBC() :
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
HRESULT GPUCompressBC::Initialize(ID3D11Device* pDevice)
{
if ( !pDevice )
if (!pDevice)
return E_INVALIDARG;
// Check for DirectCompute support
D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel();
if ( fl < D3D_FEATURE_LEVEL_10_0 )
if (fl < D3D_FEATURE_LEVEL_10_0)
{
// DirectCompute not supported on Feature Level 9.x hardware
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
if ( fl < D3D_FEATURE_LEVEL_11_0 )
if (fl < D3D_FEATURE_LEVEL_11_0)
{
// DirectCompute support on Feature Level 10.x hardware is optional, and this function needs it
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts;
HRESULT hr = pDevice->CheckFeatureSupport( D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) );
if ( FAILED(hr) )
HRESULT hr = pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts));
if (FAILED(hr))
{
memset( &hwopts, 0, sizeof(hwopts) );
memset(&hwopts, 0, sizeof(hwopts));
}
if ( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x )
if (!hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x)
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
}
// Save a device reference and obtain immediate context
m_device = pDevice;
pDevice->GetImmediateContext( m_context.ReleaseAndGetAddressOf() );
assert( m_context );
pDevice->GetImmediateContext(m_context.ReleaseAndGetAddressOf());
assert(m_context);
//--- Create compute shader library: BC6H -----------------------------------------
// Modes 11-14
HRESULT hr = pDevice->CreateComputeShader( BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateComputeShader(BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Modes 1-10
hr = pDevice->CreateComputeShader( BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Encode
hr = pDevice->CreateComputeShader( BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
//--- Create compute shader library: BC7 ------------------------------------------
// Modes 4, 5, 6
hr = pDevice->CreateComputeShader( BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Modes 1, 3, 7
hr = pDevice->CreateComputeShader( BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Modes 0, 2
hr = pDevice->CreateComputeShader( BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Encode
hr = pDevice->CreateComputeShader( BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
return S_OK;
@ -178,12 +176,12 @@ HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format, float alphaWeight, bool skip3subsets )
HRESULT GPUCompressBC::Prepare(size_t width, size_t height, DXGI_FORMAT format, float alphaWeight, bool skip3subsets)
{
if ( !width || !height || alphaWeight < 0.f )
if (!width || !height || alphaWeight < 0.f)
return E_INVALIDARG;
if ( (width > UINT32_MAX) || (height > UINT32_MAX) )
if ((width > UINT32_MAX) || (height > UINT32_MAX))
return E_INVALIDARG;
m_width = width;
@ -193,11 +191,11 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
m_skip3Subsets = skip3subsets;
size_t xblocks = std::max<size_t>( 1, (width + 3) >> 2 );
size_t yblocks = std::max<size_t>( 1, (height + 3) >> 2 );
size_t xblocks = std::max<size_t>(1, (width + 3) >> 2);
size_t yblocks = std::max<size_t>(1, (height + 3) >> 2);
size_t num_blocks = xblocks * yblocks;
switch( format )
switch (format)
{
// BC6H GPU compressor takes RGBAF32 as input
case DXGI_FORMAT_BC6H_TYPELESS:
@ -218,39 +216,39 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
default:
m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN;
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
m_bcformat = format;
auto pDevice = m_device.Get();
if ( !pDevice )
if (!pDevice)
return E_POINTER;
// Create structured buffers
size_t bufferSize = num_blocks * sizeof( BufferBC6HBC7 );
size_t bufferSize = num_blocks * sizeof(BufferBC6HBC7);
{
D3D11_BUFFER_DESC desc = {};
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
desc.StructureByteStride = sizeof( BufferBC6HBC7 );
desc.ByteWidth = static_cast<UINT>( bufferSize );
desc.StructureByteStride = sizeof(BufferBC6HBC7);
desc.ByteWidth = static_cast<UINT>(bufferSize);
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_output.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_output.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateBuffer( &desc, nullptr, m_err1.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateBuffer(&desc, nullptr, m_err1.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateBuffer( &desc, nullptr, m_err2.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateBuffer(&desc, nullptr, m_err2.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -261,10 +259,10 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
D3D11_BUFFER_DESC desc = {};
desc.Usage = D3D11_USAGE_STAGING;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.ByteWidth = static_cast<UINT>( bufferSize );
desc.ByteWidth = static_cast<UINT>(bufferSize);
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -276,10 +274,10 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.ByteWidth = sizeof( ConstantsBC6HBC7 );
desc.ByteWidth = sizeof(ConstantsBC6HBC7);
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -288,17 +286,17 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
// Create shader resource views
{
D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
desc.Buffer.NumElements = static_cast<UINT>(num_blocks);
desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
HRESULT hr = pDevice->CreateShaderResourceView( m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateShaderResourceView(m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateShaderResourceView( m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateShaderResourceView(m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -307,23 +305,23 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
// Create unordered access views
{
D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
desc.Buffer.NumElements = static_cast<UINT>(num_blocks);
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
HRESULT hr = pDevice->CreateUnorderedAccessView( m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateUnorderedAccessView(m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateUnorderedAccessView( m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateUnorderedAccessView(m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateUnorderedAccessView( m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateUnorderedAccessView(m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -335,34 +333,34 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
HRESULT GPUCompressBC::Compress(const Image& srcImage, const Image& destImage)
{
if ( !srcImage.pixels || !destImage.pixels )
if (!srcImage.pixels || !destImage.pixels)
return E_INVALIDARG;
if ( srcImage.width != destImage.width
if (srcImage.width != destImage.width
|| srcImage.height != destImage.height
|| srcImage.width != m_width
|| srcImage.height != m_height
|| srcImage.format != m_srcformat
|| destImage.format != m_bcformat )
|| destImage.format != m_bcformat)
{
return E_UNEXPECTED;
}
//--- Create input texture --------------------------------------------------------
auto pDevice = m_device.Get();
if ( !pDevice )
if (!pDevice)
return E_POINTER;
// We need to avoid the hardware doing additional colorspace conversion
DXGI_FORMAT inputFormat = ( m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
DXGI_FORMAT inputFormat = (m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
ComPtr<ID3D11Texture2D> sourceTex;
{
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = static_cast<UINT>( srcImage.width );
desc.Height = static_cast<UINT>( srcImage.height );
desc.Width = static_cast<UINT>(srcImage.width);
desc.Height = static_cast<UINT>(srcImage.height);
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = inputFormat;
@ -372,11 +370,11 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = srcImage.pixels;
initData.SysMemPitch = static_cast<DWORD>( srcImage.rowPitch );
initData.SysMemSlicePitch = static_cast<DWORD>( srcImage.slicePitch );
initData.SysMemPitch = static_cast<DWORD>(srcImage.rowPitch);
initData.SysMemSlicePitch = static_cast<DWORD>(srcImage.slicePitch);
HRESULT hr = pDevice->CreateTexture2D( &desc, &initData, sourceTex.GetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateTexture2D(&desc, &initData, sourceTex.GetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -389,8 +387,8 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
desc.Format = inputFormat;
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
HRESULT hr = pDevice->CreateShaderResourceView( sourceTex.Get(), &desc, sourceSRV.GetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateShaderResourceView(sourceTex.Get(), &desc, sourceSRV.GetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -398,7 +396,7 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
//--- Compress using DirectCompute ------------------------------------------------
bool isbc7 = false;
switch( m_bcformat )
switch (m_bcformat)
{
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
@ -418,47 +416,47 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
const UINT MAX_BLOCK_BATCH = 64;
auto pContext = m_context.Get();
if ( !pContext )
if (!pContext)
return E_UNEXPECTED;
size_t xblocks = std::max<size_t>( 1, (m_width + 3) >> 2 );
size_t yblocks = std::max<size_t>( 1, (m_height + 3) >> 2 );
size_t xblocks = std::max<size_t>(1, (m_width + 3) >> 2);
size_t yblocks = std::max<size_t>(1, (m_height + 3) >> 2);
UINT num_total_blocks = static_cast<UINT>( xblocks * yblocks );
UINT num_total_blocks = static_cast<UINT>(xblocks * yblocks);
UINT num_blocks = num_total_blocks;
int start_block_id = 0;
while (num_blocks > 0)
{
UINT n = std::min<UINT>( num_blocks, MAX_BLOCK_BATCH );
UINT n = std::min<UINT>(num_blocks, MAX_BLOCK_BATCH);
UINT uThreadGroupCount = n;
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
return hr;
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = 0;
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
param.alpha_weight = m_alphaWeight;
memcpy( mapped.pData, &param, sizeof( param ) );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap( m_constBuffer.Get(), 0 );
pContext->Unmap(m_constBuffer.Get(), 0);
}
if ( isbc7 )
if (isbc7)
{
//--- BC7 -----------------------------------------------------------------
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
RunComputeShader( pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
RunComputeShader(pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
for ( UINT i = 0; i < 3; ++i )
for (UINT i = 0; i < 3; ++i)
{
static const UINT modes[] = { 1, 3, 7 };
@ -467,141 +465,139 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
// Mode 7: err1 -> err2
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
{
ResetContext( pContext );
ResetContext(pContext);
return hr;
}
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = modes[i];
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
param.alpha_weight = m_alphaWeight;
memcpy( mapped.pData, &param, sizeof( param ) );
pContext->Unmap( m_constBuffer.Get(), 0 );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap(m_constBuffer.Get(), 0);
}
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
RunComputeShader( pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount );
RunComputeShader(pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount);
}
if ( !m_skip3Subsets )
if (!m_skip3Subsets)
{
// 3 subset modes tend to be used rarely and add significant compression time
for ( UINT i = 0; i < 2; ++i )
for (UINT i = 0; i < 2; ++i)
{
static const UINT modes[] = { 0, 2 };
// Mode 0: err2 -> err1
// Mode 2: err1 -> err2
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
{
ResetContext( pContext );
ResetContext(pContext);
return hr;
}
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = modes[i];
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
param.alpha_weight = m_alphaWeight;
memcpy( mapped.pData, &param, sizeof( param ) );
pContext->Unmap( m_constBuffer.Get(), 0 );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap(m_constBuffer.Get(), 0);
}
pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get();
RunComputeShader( pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount );
RunComputeShader(pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount);
}
}
pSRVs[1] = m_err2SRV.Get();
RunComputeShader( pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
RunComputeShader(pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
}
else
{
//--- BC6H ----------------------------------------------------------------
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
RunComputeShader( pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
RunComputeShader(pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
for ( UINT i = 0; i < 10; ++i )
for (UINT i = 0; i < 10; ++i)
{
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
{
ResetContext( pContext );
ResetContext(pContext);
return hr;
}
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = i;
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
memcpy( mapped.pData, &param, sizeof( param ) );
pContext->Unmap( m_constBuffer.Get(), 0 );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap(m_constBuffer.Get(), 0);
}
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
RunComputeShader( pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
RunComputeShader(pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
}
pSRVs[1] = m_err1SRV.Get();
RunComputeShader( pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
RunComputeShader(pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
}
start_block_id += n;
num_blocks -= n;
}
ResetContext( pContext );
ResetContext(pContext);
//--- Copy output texture back to CPU ---------------------------------------------
pContext->CopyResource( m_outputCPU.Get(), m_output.Get() );
pContext->CopyResource(m_outputCPU.Get(), m_output.Get());
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped );
if ( SUCCEEDED(hr) )
HRESULT hr = pContext->Map(m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped);
if (SUCCEEDED(hr))
{
const uint8_t *pSrc = reinterpret_cast<const uint8_t *>( mapped.pData );
const uint8_t *pSrc = reinterpret_cast<const uint8_t *>(mapped.pData);
uint8_t *pDest = destImage.pixels;
size_t pitch = xblocks * sizeof( BufferBC6HBC7 );
size_t pitch = xblocks * sizeof(BufferBC6HBC7);
size_t rows = std::max<size_t>( 1, ( destImage.height + 3 ) >> 2 );
size_t rows = std::max<size_t>(1, (destImage.height + 3) >> 2);
for( size_t h = 0; h < rows; ++h )
for (size_t h = 0; h < rows; ++h)
{
memcpy( pDest, pSrc, destImage.rowPitch );
memcpy(pDest, pSrc, destImage.rowPitch);
pSrc += pitch;
pDest += destImage.rowPitch;
}
pContext->Unmap( m_outputCPU.Get(), 0 );
pContext->Unmap(m_outputCPU.Get(), 0);
}
return hr;
}
}; // namespace

View File

@ -33,7 +33,7 @@
#include <ocidl.h>
#define DIRECTX_TEX_VERSION 134
#define DIRECTX_TEX_VERSION 140
struct IWICImagingFactory;
struct IWICMetadataQueryReader;
@ -204,21 +204,21 @@ namespace DirectX
// Filtering mode to use for any required image resizing (only needed when loading arrays of differently sized images; defaults to Fant)
};
HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ const wchar_t* szFile,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_ TexMetadata& metadata,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
HRESULT __cdecl GetMetadataFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_ TexMetadata& metadata,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
@ -238,13 +238,16 @@ namespace DirectX
{
public:
ScratchImage()
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) {}
: m_nimages(0), m_size(0), m_image(nullptr), m_memory(nullptr) {}
ScratchImage(ScratchImage&& moveFrom)
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) { *this = std::move(moveFrom); }
: m_nimages(0), m_size(0), m_image(nullptr), m_memory(nullptr) { *this = std::move(moveFrom); }
~ScratchImage() { Release(); }
ScratchImage& __cdecl operator= (ScratchImage&& moveFrom);
ScratchImage(const ScratchImage&) = delete;
ScratchImage& operator=(const ScratchImage&) = delete;
HRESULT __cdecl Initialize( _In_ const TexMetadata& mdata, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl Initialize1D( _In_ DXGI_FORMAT fmt, _In_ size_t length, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
@ -261,27 +264,23 @@ namespace DirectX
bool __cdecl OverrideFormat( _In_ DXGI_FORMAT f );
const TexMetadata& __cdecl GetMetadata() const { return _metadata; }
const TexMetadata& __cdecl GetMetadata() const { return m_metadata; }
const Image* __cdecl GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const;
const Image* __cdecl GetImages() const { return _image; }
size_t __cdecl GetImageCount() const { return _nimages; }
const Image* __cdecl GetImages() const { return m_image; }
size_t __cdecl GetImageCount() const { return m_nimages; }
uint8_t* __cdecl GetPixels() const { return _memory; }
size_t __cdecl GetPixelsSize() const { return _size; }
uint8_t* __cdecl GetPixels() const { return m_memory; }
size_t __cdecl GetPixelsSize() const { return m_size; }
bool __cdecl IsAlphaAllOpaque() const;
private:
size_t _nimages;
size_t _size;
TexMetadata _metadata;
Image* _image;
uint8_t* _memory;
// Hide copy constructor and assignment operator
ScratchImage( const ScratchImage& );
ScratchImage& operator=( const ScratchImage& );
size_t m_nimages;
size_t m_size;
TexMetadata m_metadata;
Image* m_image;
uint8_t* m_memory;
};
//---------------------------------------------------------------------------------
@ -289,35 +288,34 @@ namespace DirectX
class Blob
{
public:
Blob() : _buffer(nullptr), _size(0) {}
Blob(Blob&& moveFrom) : _buffer(nullptr), _size(0) { *this = std::move(moveFrom); }
Blob() : m_buffer(nullptr), m_size(0) {}
Blob(Blob&& moveFrom) : m_buffer(nullptr), m_size(0) { *this = std::move(moveFrom); }
~Blob() { Release(); }
Blob& __cdecl operator= (Blob&& moveFrom);
Blob(const Blob&) = delete;
Blob& operator=(const Blob&) = delete;
HRESULT __cdecl Initialize( _In_ size_t size );
void __cdecl Release();
void *__cdecl GetBufferPointer() const { return _buffer; }
size_t __cdecl GetBufferSize() const { return _size; }
void *__cdecl GetBufferPointer() const { return m_buffer; }
size_t __cdecl GetBufferSize() const { return m_size; }
private:
void* _buffer;
size_t _size;
// Hide copy constructor and assignment operator
Blob( const Blob& );
Blob& operator=( const Blob& );
void* m_buffer;
size_t m_size;
};
//---------------------------------------------------------------------------------
// Image I/O
// DDS operations
HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl LoadFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl LoadFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags,
@ -325,23 +323,23 @@ namespace DirectX
HRESULT __cdecl SaveToDDSMemory( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags,
_Out_ Blob& blob );
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ const wchar_t* szFile );
HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ const wchar_t* szFile );
// TGA operations
HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl LoadFromTGAFile( _In_z_ LPCWSTR szFile,
HRESULT __cdecl LoadFromTGAFile( _In_z_ const wchar_t* szFile,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );
HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ LPCWSTR szFile );
HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ const wchar_t* szFile );
// WIC operations
HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
HRESULT __cdecl LoadFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl LoadFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
@ -353,10 +351,10 @@ namespace DirectX
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
HRESULT __cdecl SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
HRESULT __cdecl SaveToWICFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
//---------------------------------------------------------------------------------

View File

@ -113,7 +113,7 @@ inline HRESULT __cdecl SaveToDDSMemory(const Image& image, DWORD flags, Blob& bl
}
_Use_decl_annotations_
inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, LPCWSTR szFile)
inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, const wchar_t* szFile)
{
TexMetadata mdata = {};
mdata.width = image.width;

View File

@ -22,31 +22,31 @@
#include "bc.h"
using namespace DirectX;
namespace DirectX
namespace
{
inline DWORD GetBCFlags(_In_ DWORD compress)
{
static_assert(TEX_COMPRESS_RGB_DITHER == BC_FLAGS_DITHER_RGB, "TEX_COMPRESS_* flags should match BC_FLAGS_*");
static_assert(TEX_COMPRESS_A_DITHER == BC_FLAGS_DITHER_A, "TEX_COMPRESS_* flags should match BC_FLAGS_*");
static_assert(TEX_COMPRESS_DITHER == (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*");
static_assert(TEX_COMPRESS_UNIFORM == BC_FLAGS_UNIFORM, "TEX_COMPRESS_* flags should match BC_FLAGS_*");
static_assert(TEX_COMPRESS_BC7_USE_3SUBSETS == BC_FLAGS_USE_3SUBSETS, "TEX_COMPRESS_* flags should match BC_FLAGS_*");
return (compress & (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A | BC_FLAGS_UNIFORM | BC_FLAGS_USE_3SUBSETS));
}
inline static DWORD _GetBCFlags( _In_ DWORD compress )
{
static_assert( TEX_COMPRESS_RGB_DITHER == BC_FLAGS_DITHER_RGB, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_A_DITHER == BC_FLAGS_DITHER_A, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_DITHER == (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_UNIFORM == BC_FLAGS_UNIFORM, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
static_assert( TEX_COMPRESS_BC7_USE_3SUBSETS == BC_FLAGS_USE_3SUBSETS, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
return ( compress & (BC_FLAGS_DITHER_RGB|BC_FLAGS_DITHER_A|BC_FLAGS_UNIFORM|BC_FLAGS_USE_3SUBSETS) );
}
inline DWORD GetSRGBFlags(_In_ DWORD compress)
{
static_assert(TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
return (compress & TEX_COMPRESS_SRGB);
}
inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
{
static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
return ( compress & TEX_COMPRESS_SRGB );
}
inline static bool _DetermineEncoderSettings( _In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags )
{
switch(format)
inline bool DetermineEncoderSettings(_In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags)
{
switch (format)
{
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; cflags = 0; break;
@ -66,32 +66,36 @@ inline static bool _DetermineEncoderSettings( _In_ DXGI_FORMAT format, _Out_ BC_
}
return true;
}
}
//-------------------------------------------------------------------------------------
static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
_In_ DWORD srgb, _In_ float alphaRef )
{
if ( !image.pixels || !result.pixels )
//-------------------------------------------------------------------------------------
HRESULT CompressBC(
const Image& image,
const Image& result,
DWORD bcflags,
DWORD srgb,
float alphaRef)
{
if (!image.pixels || !result.pixels)
return E_POINTER;
assert( image.width == result.width );
assert( image.height == result.height );
assert(image.width == result.width);
assert(image.height == result.height);
const DXGI_FORMAT format = image.format;
size_t sbpp = BitsPerPixel( format );
if ( !sbpp )
size_t sbpp = BitsPerPixel(format);
if (!sbpp)
return E_FAIL;
if ( sbpp < 8 )
if (sbpp < 8)
{
// We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
// Round to bytes
sbpp = ( sbpp + 7 ) / 8;
sbpp = (sbpp + 7) / 8;
uint8_t *pDest = result.pixels;
@ -99,124 +103,128 @@ static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _
BC_ENCODE pfEncode;
size_t blocksize;
DWORD cflags;
if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (!DetermineEncoderSettings(result.format, pfEncode, blocksize, cflags))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
__declspec(align(16)) XMVECTOR temp[16];
const uint8_t *pSrc = image.pixels;
const uint8_t *pEnd = image.pixels + image.slicePitch;
const size_t rowPitch = image.rowPitch;
for( size_t h=0; h < image.height; h += 4 )
for (size_t h = 0; h < image.height; h += 4)
{
const uint8_t *sptr = pSrc;
uint8_t* dptr = pDest;
size_t ph = std::min<size_t>( 4, image.height - h );
size_t ph = std::min<size_t>(4, image.height - h);
size_t w = 0;
for( size_t count = 0; (count < result.rowPitch) && (w < image.width); count += blocksize, w += 4 )
for (size_t count = 0; (count < result.rowPitch) && (w < image.width); count += blocksize, w += 4)
{
size_t pw = std::min<size_t>( 4, image.width - w );
assert( pw > 0 && ph > 0 );
size_t pw = std::min<size_t>(4, image.width - w);
assert(pw > 0 && ph > 0);
ptrdiff_t bytesLeft = pEnd - sptr;
assert( bytesLeft > 0 );
size_t bytesToRead = std::min<size_t>( rowPitch, bytesLeft );
if ( !_LoadScanline( &temp[0], pw, sptr, bytesToRead, format ) )
assert(bytesLeft > 0);
size_t bytesToRead = std::min<size_t>(rowPitch, bytesLeft);
if (!_LoadScanline(&temp[0], pw, sptr, bytesToRead, format))
return E_FAIL;
if ( ph > 1 )
if (ph > 1)
{
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch );
if ( !_LoadScanline( &temp[4], pw, sptr + rowPitch, bytesToRead, format ) )
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch);
if (!_LoadScanline(&temp[4], pw, sptr + rowPitch, bytesToRead, format))
return E_FAIL;
if ( ph > 2 )
if (ph > 2)
{
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 2 );
if ( !_LoadScanline( &temp[8], pw, sptr + rowPitch*2, bytesToRead, format ) )
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 2);
if (!_LoadScanline(&temp[8], pw, sptr + rowPitch * 2, bytesToRead, format))
return E_FAIL;
if ( ph > 3 )
if (ph > 3)
{
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 3 );
if ( !_LoadScanline( &temp[12], pw, sptr + rowPitch*3, bytesToRead, format ) )
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 3);
if (!_LoadScanline(&temp[12], pw, sptr + rowPitch * 3, bytesToRead, format))
return E_FAIL;
}
}
}
if ( pw != 4 || ph != 4 )
if (pw != 4 || ph != 4)
{
// Replicate pixels for partial block
static const size_t uSrc[] = { 0, 0, 0, 1 };
if ( pw < 4 )
if (pw < 4)
{
for( size_t t = 0; t < ph && t < 4; ++t )
for (size_t t = 0; t < ph && t < 4; ++t)
{
for( size_t s = pw; s < 4; ++s )
for (size_t s = pw; s < 4; ++s)
{
#pragma prefast(suppress: 26000, "PREFAST false positive")
temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
temp[(t << 2) | s] = temp[(t << 2) | uSrc[s]];
}
}
}
if ( ph < 4 )
if (ph < 4)
{
for( size_t t = ph; t < 4; ++t )
for (size_t t = ph; t < 4; ++t)
{
for( size_t s = 0; s < 4; ++s )
for (size_t s = 0; s < 4; ++s)
{
#pragma prefast(suppress: 26000, "PREFAST false positive")
temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
temp[(t << 2) | s] = temp[(uSrc[t] << 2) | s];
}
}
}
}
_ConvertScanline( temp, 16, result.format, format, cflags | srgb );
_ConvertScanline(temp, 16, result.format, format, cflags | srgb);
if ( pfEncode )
pfEncode( dptr, temp, bcflags );
if (pfEncode)
pfEncode(dptr, temp, bcflags);
else
D3DXEncodeBC1( dptr, temp, alphaRef, bcflags );
D3DXEncodeBC1(dptr, temp, alphaRef, bcflags);
sptr += sbpp*4;
sptr += sbpp * 4;
dptr += blocksize;
}
pSrc += rowPitch*4;
pSrc += rowPitch * 4;
pDest += result.rowPitch;
}
return S_OK;
}
}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
#ifdef _OPENMP
static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
_In_ DWORD srgb, _In_ float alphaRef )
{
if ( !image.pixels || !result.pixels )
HRESULT CompressBC_Parallel(
const Image& image,
const Image& result,
DWORD bcflags,
DWORD srgb,
float alphaRef)
{
if (!image.pixels || !result.pixels)
return E_POINTER;
assert( image.width == result.width );
assert( image.height == result.height );
assert(image.width == result.width);
assert(image.height == result.height);
const DXGI_FORMAT format = image.format;
size_t sbpp = BitsPerPixel( format );
if ( !sbpp )
size_t sbpp = BitsPerPixel(format);
if (!sbpp)
return E_FAIL;
if ( sbpp < 8 )
if (sbpp < 8)
{
// We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
// Round to bytes
sbpp = ( sbpp + 7 ) / 8;
sbpp = (sbpp + 7) / 8;
const uint8_t *pEnd = image.pixels + image.slicePitch;
@ -224,110 +232,109 @@ static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image&
BC_ENCODE pfEncode;
size_t blocksize;
DWORD cflags;
if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (!DetermineEncoderSettings(result.format, pfEncode, blocksize, cflags))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Refactored version of loop to support parallel independance
const size_t nBlocks = std::max<size_t>(1, (image.width + 3) / 4 ) * std::max<size_t>(1, (image.height + 3) / 4 );
const size_t nBlocks = std::max<size_t>(1, (image.width + 3) / 4) * std::max<size_t>(1, (image.height + 3) / 4);
bool fail = false;
#pragma omp parallel for
for( int nb=0; nb < static_cast<int>( nBlocks ); ++nb )
for (int nb = 0; nb < static_cast<int>(nBlocks); ++nb)
{
int nbWidth = std::max<int>(1, int( (image.width + 3) / 4 ) );
int nbWidth = std::max<int>(1, int((image.width + 3) / 4));
int y = nb / nbWidth;
int x = ( nb - (y*nbWidth) ) * 4;
int x = (nb - (y*nbWidth)) * 4;
y *= 4;
assert( (x >= 0) && (x < int(image.width)) );
assert( (y >= 0) && (y < int(image.height)) );
assert((x >= 0) && (x < int(image.width)));
assert((y >= 0) && (y < int(image.height)));
size_t rowPitch = image.rowPitch;
const uint8_t *pSrc = image.pixels + (y*rowPitch) + (x*sbpp);
uint8_t *pDest = result.pixels + (nb*blocksize);
size_t ph = std::min<size_t>( 4, image.height - y );
size_t pw = std::min<size_t>( 4, image.width - x );
assert( pw > 0 && ph > 0 );
size_t ph = std::min<size_t>(4, image.height - y);
size_t pw = std::min<size_t>(4, image.width - x);
assert(pw > 0 && ph > 0);
ptrdiff_t bytesLeft = pEnd - pSrc;
assert( bytesLeft > 0 );
size_t bytesToRead = std::min<size_t>( rowPitch, bytesLeft );
assert(bytesLeft > 0);
size_t bytesToRead = std::min<size_t>(rowPitch, bytesLeft);
__declspec(align(16)) XMVECTOR temp[16];
if ( !_LoadScanline( &temp[0], pw, pSrc, bytesToRead, format ) )
if (!_LoadScanline(&temp[0], pw, pSrc, bytesToRead, format))
fail = true;
if ( ph > 1 )
if (ph > 1)
{
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch );
if ( !_LoadScanline( &temp[4], pw, pSrc + rowPitch, bytesToRead, format ) )
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch);
if (!_LoadScanline(&temp[4], pw, pSrc + rowPitch, bytesToRead, format))
fail = true;
if ( ph > 2 )
if (ph > 2)
{
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 2 );
if ( !_LoadScanline( &temp[8], pw, pSrc + rowPitch*2, bytesToRead, format ) )
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 2);
if (!_LoadScanline(&temp[8], pw, pSrc + rowPitch * 2, bytesToRead, format))
fail = true;
if ( ph > 3 )
if (ph > 3)
{
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 3 );
if ( !_LoadScanline( &temp[12], pw, pSrc + rowPitch*3, bytesToRead, format ) )
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 3);
if (!_LoadScanline(&temp[12], pw, pSrc + rowPitch * 3, bytesToRead, format))
fail = true;
}
}
}
if ( pw != 4 || ph != 4 )
if (pw != 4 || ph != 4)
{
// Replicate pixels for partial block
static const size_t uSrc[] = { 0, 0, 0, 1 };
if ( pw < 4 )
if (pw < 4)
{
for( size_t t = 0; t < ph && t < 4; ++t )
for (size_t t = 0; t < ph && t < 4; ++t)
{
for( size_t s = pw; s < 4; ++s )
for (size_t s = pw; s < 4; ++s)
{
temp[ (t << 2) | s ] = temp[ (t << 2) | uSrc[s] ];
temp[(t << 2) | s] = temp[(t << 2) | uSrc[s]];
}
}
}
if ( ph < 4 )
if (ph < 4)
{
for( size_t t = ph; t < 4; ++t )
for (size_t t = ph; t < 4; ++t)
{
for( size_t s = 0; s < 4; ++s )
for (size_t s = 0; s < 4; ++s)
{
temp[ (t << 2) | s ] = temp[ (uSrc[t] << 2) | s ];
temp[(t << 2) | s] = temp[(uSrc[t] << 2) | s];
}
}
}
}
_ConvertScanline( temp, 16, result.format, format, cflags | srgb );
_ConvertScanline(temp, 16, result.format, format, cflags | srgb);
if ( pfEncode )
pfEncode( pDest, temp, bcflags );
if (pfEncode)
pfEncode(pDest, temp, bcflags);
else
D3DXEncodeBC1( pDest, temp, alphaRef, bcflags );
D3DXEncodeBC1(pDest, temp, alphaRef, bcflags);
}
return (fail) ? E_FAIL : S_OK;
}
}
#endif // _OPENMP
//-------------------------------------------------------------------------------------
static DXGI_FORMAT _DefaultDecompress( _In_ DXGI_FORMAT format )
{
switch( format )
//-------------------------------------------------------------------------------------
DXGI_FORMAT DefaultDecompress(_In_ DXGI_FORMAT format)
{
switch (format)
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
@ -369,39 +376,39 @@ static DXGI_FORMAT _DefaultDecompress( _In_ DXGI_FORMAT format )
default:
return DXGI_FORMAT_UNKNOWN;
}
}
}
//-------------------------------------------------------------------------------------
static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result )
{
if ( !cImage.pixels || !result.pixels )
//-------------------------------------------------------------------------------------
HRESULT DecompressBC(_In_ const Image& cImage, _In_ const Image& result)
{
if (!cImage.pixels || !result.pixels)
return E_POINTER;
assert( cImage.width == result.width );
assert( cImage.height == result.height );
assert(cImage.width == result.width);
assert(cImage.height == result.height);
const DXGI_FORMAT format = result.format;
size_t dbpp = BitsPerPixel( format );
if ( !dbpp )
size_t dbpp = BitsPerPixel(format);
if (!dbpp)
return E_FAIL;
if ( dbpp < 8 )
if (dbpp < 8)
{
// We don't support decompressing to monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
// Round to bytes
dbpp = ( dbpp + 7 ) / 8;
dbpp = (dbpp + 7) / 8;
uint8_t *pDest = result.pixels;
if ( !pDest )
if (!pDest)
return E_POINTER;
// Promote "typeless" BC formats
DXGI_FORMAT cformat;
switch( cImage.format )
switch (cImage.format)
{
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
@ -416,7 +423,7 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
// Determine BC format decoder
BC_DECODE pfDecode;
size_t sbpp;
switch(cformat)
switch (cformat)
{
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
@ -433,68 +440,70 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
__declspec(align(16)) XMVECTOR temp[16];
const uint8_t *pSrc = cImage.pixels;
const size_t rowPitch = result.rowPitch;
for( size_t h=0; h < cImage.height; h += 4 )
for (size_t h = 0; h < cImage.height; h += 4)
{
const uint8_t *sptr = pSrc;
uint8_t* dptr = pDest;
size_t ph = std::min<size_t>( 4, cImage.height - h );
size_t ph = std::min<size_t>(4, cImage.height - h);
size_t w = 0;
for( size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4 )
for (size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4)
{
pfDecode( temp, sptr );
_ConvertScanline( temp, 16, format, cformat, 0 );
pfDecode(temp, sptr);
_ConvertScanline(temp, 16, format, cformat, 0);
size_t pw = std::min<size_t>( 4, cImage.width - w );
assert( pw > 0 && ph > 0 );
size_t pw = std::min<size_t>(4, cImage.width - w);
assert(pw > 0 && ph > 0);
if ( !_StoreScanline( dptr, rowPitch, format, &temp[0], pw ) )
if (!_StoreScanline(dptr, rowPitch, format, &temp[0], pw))
return E_FAIL;
if ( ph > 1 )
if (ph > 1)
{
if ( !_StoreScanline( dptr + rowPitch, rowPitch, format, &temp[4], pw ) )
if (!_StoreScanline(dptr + rowPitch, rowPitch, format, &temp[4], pw))
return E_FAIL;
if ( ph > 2 )
if (ph > 2)
{
if ( !_StoreScanline( dptr + rowPitch*2, rowPitch, format, &temp[8], pw ) )
if (!_StoreScanline(dptr + rowPitch * 2, rowPitch, format, &temp[8], pw))
return E_FAIL;
if ( ph > 3 )
if (ph > 3)
{
if ( !_StoreScanline( dptr + rowPitch*3, rowPitch, format, &temp[12], pw ) )
if (!_StoreScanline(dptr + rowPitch * 3, rowPitch, format, &temp[12], pw))
return E_FAIL;
}
}
}
sptr += sbpp;
dptr += dbpp*4;
dptr += dbpp * 4;
}
pSrc += cImage.rowPitch;
pDest += rowPitch*4;
pDest += rowPitch * 4;
}
return S_OK;
}
}
//-------------------------------------------------------------------------------------
bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
namespace DirectX
{
if ( !cImage.pixels )
bool _IsAlphaAllOpaqueBC(_In_ const Image& cImage)
{
if (!cImage.pixels)
return false;
// Promote "typeless" BC formats
DXGI_FORMAT cformat;
switch( cImage.format )
switch (cImage.format)
{
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
@ -506,7 +515,7 @@ bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
// Determine BC format decoder
BC_DECODE pfDecode;
size_t sbpp;
switch(cformat)
switch (cformat)
{
case DXGI_FORMAT_BC1_UNORM:
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
@ -526,37 +535,37 @@ bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
__declspec(align(16)) XMVECTOR temp[16];
const uint8_t *pPixels = cImage.pixels;
for( size_t h = 0; h < cImage.height; h += 4 )
for (size_t h = 0; h < cImage.height; h += 4)
{
const uint8_t *ptr = pPixels;
size_t ph = std::min<size_t>( 4, cImage.height - h );
size_t ph = std::min<size_t>(4, cImage.height - h);
size_t w = 0;
for( size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4 )
for (size_t count = 0; (count < cImage.rowPitch) && (w < cImage.width); count += sbpp, w += 4)
{
pfDecode( temp, ptr );
pfDecode(temp, ptr);
size_t pw = std::min<size_t>( 4, cImage.width - w );
assert( pw > 0 && ph > 0 );
size_t pw = std::min<size_t>(4, cImage.width - w);
assert(pw > 0 && ph > 0);
if ( pw == 4 && ph == 4 )
if (pw == 4 && ph == 4)
{
// Full blocks
for( size_t j = 0; j < 16; ++j )
for (size_t j = 0; j < 16; ++j)
{
XMVECTOR alpha = XMVectorSplatW( temp[j] );
if ( XMVector4Less( alpha, threshold ) )
XMVECTOR alpha = XMVectorSplatW(temp[j]);
if (XMVector4Less(alpha, threshold))
return false;
}
}
else
{
// Handle partial blocks
for( size_t y = 0; y < ph; ++y )
for (size_t y = 0; y < ph; ++y)
{
for( size_t x = 0; x < pw; ++x )
for (size_t x = 0; x < pw; ++x)
{
XMVECTOR alpha = XMVectorSplatW( temp[ y * 4 + x ] );
if ( XMVector4Less( alpha, threshold ) )
XMVECTOR alpha = XMVectorSplatW(temp[y * 4 + x]);
if (XMVector4Less(alpha, threshold))
return false;
}
}
@ -569,7 +578,8 @@ bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
}
return true;
}
}
};
//=====================================================================================
@ -580,22 +590,27 @@ bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
// Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& image )
HRESULT DirectX::Compress(
const Image& srcImage,
DXGI_FORMAT format,
DWORD compress,
float alphaRef,
ScratchImage& image)
{
if ( IsCompressed(srcImage.format) || !IsCompressed(format) )
if (IsCompressed(srcImage.format) || !IsCompressed(format))
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format)
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Create compressed image
HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
@ -607,76 +622,82 @@ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, flo
#ifndef _OPENMP
return E_NOTIMPL;
#else
hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), alphaRef);
#endif // _OPENMP
}
else
{
hr = _CompressBC( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
hr = CompressBC(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), alphaRef);
}
if ( FAILED(hr) )
if (FAILED(hr))
image.Release();
return hr;
}
_Use_decl_annotations_
HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages )
HRESULT DirectX::Compress(
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DXGI_FORMAT format,
DWORD compress,
float alphaRef,
ScratchImage& cImages)
{
if ( !srcImages || !nimages )
if (!srcImages || !nimages)
return E_INVALIDARG;
if ( IsCompressed(metadata.format) || !IsCompressed(format) )
if (IsCompressed(metadata.format) || !IsCompressed(format))
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format)
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
cImages.Release();
TexMetadata mdata2 = metadata;
mdata2.format = format;
HRESULT hr = cImages.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = cImages.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != cImages.GetImageCount() )
if (nimages != cImages.GetImageCount())
{
cImages.Release();
return E_FAIL;
}
const Image* dest = cImages.GetImages();
if ( !dest )
if (!dest)
{
cImages.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
assert( dest[ index ].format == format );
assert(dest[index].format == format);
const Image& src = srcImages[ index ];
const Image& src = srcImages[index];
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
if (src.width != dest[index].width || src.height != dest[index].height)
{
cImages.Release();
return E_FAIL;
}
if ( (compress & TEX_COMPRESS_PARALLEL) )
if ((compress & TEX_COMPRESS_PARALLEL))
{
#ifndef _OPENMP
return E_NOTIMPL;
#else
if ( compress & TEX_COMPRESS_PARALLEL )
if (compress & TEX_COMPRESS_PARALLEL)
{
hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
if ( FAILED(hr) )
hr = CompressBC_Parallel(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), alphaRef);
if (FAILED(hr))
{
cImages.Release();
return hr;
@ -686,8 +707,8 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met
}
else
{
hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
if ( FAILED(hr) )
hr = CompressBC(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), alphaRef);
if (FAILED(hr))
{
cImages.Release();
return hr;
@ -703,16 +724,19 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met
// Decompression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image )
HRESULT DirectX::Decompress(
const Image& cImage,
DXGI_FORMAT format,
ScratchImage& image)
{
if ( !IsCompressed(cImage.format) || IsCompressed(format) )
if (!IsCompressed(cImage.format) || IsCompressed(format))
return E_INVALIDARG;
if ( format == DXGI_FORMAT_UNKNOWN )
if (format == DXGI_FORMAT_UNKNOWN)
{
// Pick a default decompressed format based on BC input format
format = _DefaultDecompress( cImage.format );
if ( format == DXGI_FORMAT_UNKNOWN )
format = DefaultDecompress(cImage.format);
if (format == DXGI_FORMAT_UNKNOWN)
{
// Input is not a compressed format
return E_INVALIDARG;
@ -720,48 +744,52 @@ HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image
}
else
{
if ( !IsValid(format) )
if (!IsValid(format))
return E_INVALIDARG;
if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format) || IsPlanar(format) || IsPalettized(format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
// Create decompressed image
HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(format, cImage.width, cImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
}
// Decompress single image
hr = _DecompressBC( cImage, *img );
if ( FAILED(hr) )
hr = DecompressBC(cImage, *img);
if (FAILED(hr))
image.Release();
return hr;
}
_Use_decl_annotations_
HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, ScratchImage& images )
HRESULT DirectX::Decompress(
const Image* cImages,
size_t nimages,
const TexMetadata& metadata,
DXGI_FORMAT format,
ScratchImage& images)
{
if ( !cImages || !nimages )
if (!cImages || !nimages)
return E_INVALIDARG;
if ( !IsCompressed(metadata.format) || IsCompressed(format) )
if (!IsCompressed(metadata.format) || IsCompressed(format))
return E_INVALIDARG;
if ( format == DXGI_FORMAT_UNKNOWN )
if (format == DXGI_FORMAT_UNKNOWN)
{
// Pick a default decompressed format based on BC input format
format = _DefaultDecompress( cImages[0].format );
if ( format == DXGI_FORMAT_UNKNOWN )
format = DefaultDecompress(cImages[0].format);
if (format == DXGI_FORMAT_UNKNOWN)
{
// Input is not a compressed format
return E_FAIL;
@ -769,53 +797,53 @@ HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& met
}
else
{
if ( !IsValid(format) )
if (!IsValid(format))
return E_INVALIDARG;
if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format) || IsPlanar(format) || IsPalettized(format))
HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
images.Release();
TexMetadata mdata2 = metadata;
mdata2.format = format;
HRESULT hr = images.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = images.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != images.GetImageCount() )
if (nimages != images.GetImageCount())
{
images.Release();
return E_FAIL;
}
const Image* dest = images.GetImages();
if ( !dest )
if (!dest)
{
images.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
assert( dest[ index ].format == format );
assert(dest[index].format == format);
const Image& src = cImages[ index ];
if ( !IsCompressed( src.format ) )
const Image& src = cImages[index];
if (!IsCompressed(src.format))
{
images.Release();
return E_FAIL;
}
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
if (src.width != dest[index].width || src.height != dest[index].height)
{
images.Release();
return E_FAIL;
}
hr = _DecompressBC( src, dest[ index ] );
if ( FAILED(hr) )
hr = DecompressBC(src, dest[index]);
if (FAILED(hr))
{
images.Release();
return hr;
@ -824,5 +852,3 @@ HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& met
return S_OK;
}
}; // namespace

View File

@ -17,65 +17,70 @@
#include "bcdirectcompute.h"
namespace DirectX
{
using namespace DirectX;
inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
namespace
{
static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
return ( compress & TEX_COMPRESS_SRGB );
}
inline DWORD GetSRGBFlags(_In_ DWORD compress)
{
static_assert(TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
return (compress & TEX_COMPRESS_SRGB);
}
//-------------------------------------------------------------------------------------
// Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed
//-------------------------------------------------------------------------------------
static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& image, bool srgb, _In_ DWORD filter )
{
if ( !srcImage.pixels )
//-------------------------------------------------------------------------------------
// Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed
//-------------------------------------------------------------------------------------
HRESULT ConvertToRGBA32(
const Image& srcImage,
ScratchImage& image,
bool srgb,
DWORD filter)
{
if (!srcImage.pixels)
return E_POINTER;
DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
}
uint8_t* pDest = img->pixels;
if ( !pDest )
if (!pDest)
{
image.Release();
return E_POINTER;
}
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( ( sizeof(XMVECTOR) * srcImage.width ), 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR) * srcImage.width), 16)));
if (!scanline)
{
image.Release();
return E_OUTOFMEMORY;
}
const uint8_t *pSrc = srcImage.pixels;
for( size_t h = 0; h < srcImage.height; ++h )
for (size_t h = 0; h < srcImage.height; ++h)
{
if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
{
image.Release();
return E_FAIL;
}
_ConvertScanline( scanline.get(), srcImage.width, format, srcImage.format, filter );
_ConvertScanline(scanline.get(), srcImage.width, format, srcImage.format, filter);
if ( !_StoreScanline( pDest, img->rowPitch, format, scanline.get(), srcImage.width ) )
if (!_StoreScanline(pDest, img->rowPitch, format, scanline.get(), srcImage.width))
{
image.Release();
return E_FAIL;
@ -86,70 +91,77 @@ static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage&
}
return S_OK;
}
}
//-------------------------------------------------------------------------------------
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
//-------------------------------------------------------------------------------------
static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image, _In_ DWORD filter )
{
if ( !srcImage.pixels )
//-------------------------------------------------------------------------------------
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
//-------------------------------------------------------------------------------------
HRESULT ConvertToRGBAF32(
const Image& srcImage,
ScratchImage& image,
DWORD filter)
{
if (!srcImage.pixels)
return E_POINTER;
HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
}
uint8_t* pDest = img->pixels;
if ( !pDest )
if (!pDest)
{
image.Release();
return E_POINTER;
}
const uint8_t *pSrc = srcImage.pixels;
for( size_t h = 0; h < srcImage.height; ++h )
for (size_t h = 0; h < srcImage.height; ++h)
{
if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
if (!_LoadScanline(reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
{
image.Release();
return E_FAIL;
}
_ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
_ConvertScanline(reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter);
pSrc += srcImage.rowPitch;
pDest += img->rowPitch;
}
return S_OK;
}
}
//-------------------------------------------------------------------------------------
// Compress using GPU, converting to the proper input format for the shader if needed
//-------------------------------------------------------------------------------------
inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& srcImage, _In_ const Image& destImage, _In_ DWORD compress )
{
if ( !gpubc )
//-------------------------------------------------------------------------------------
// Compress using GPU, converting to the proper input format for the shader if needed
//-------------------------------------------------------------------------------------
inline HRESULT GPUCompress(
_In_ GPUCompressBC* gpubc,
const Image& srcImage,
const Image& destImage,
DWORD compress)
{
if (!gpubc)
return E_POINTER;
assert( srcImage.pixels && destImage.pixels );
assert(srcImage.pixels && destImage.pixels);
DXGI_FORMAT format = gpubc->GetSourceFormat();
if ( srcImage.format == format )
if (srcImage.format == format)
{
// Input is already in our required source format
return gpubc->Compress( srcImage, destImage );
return gpubc->Compress(srcImage, destImage);
}
else
{
@ -157,20 +169,20 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
ScratchImage image;
HRESULT hr;
DWORD srgb = _GetSRGBFlags( compress );
DWORD srgb = GetSRGBFlags(compress);
switch( format )
switch (format)
{
case DXGI_FORMAT_R8G8B8A8_UNORM:
hr = _ConvertToRGBA32( srcImage, image, false, srgb );
hr = ConvertToRGBA32(srcImage, image, false, srgb);
break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
hr = _ConvertToRGBA32( srcImage, image, true, srgb );
hr = ConvertToRGBA32(srcImage, image, true, srgb);
break;
case DXGI_FORMAT_R32G32B32A32_FLOAT:
hr = _ConvertToRGBAF32( srcImage, image, srgb );
hr = ConvertToRGBAF32(srcImage, image, srgb);
break;
default:
@ -178,17 +190,17 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
break;
}
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = image.GetImage(0, 0, 0);
if (!img)
return E_POINTER;
return gpubc->Compress( *img, destImage );
return gpubc->Compress(*img, destImage);
}
}
}
};
//=====================================================================================
// Entry-points
@ -198,94 +210,107 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
// Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& image )
HRESULT DirectX::Compress(
ID3D11Device* pDevice,
const Image& srcImage,
DXGI_FORMAT format,
DWORD compress,
float alphaWeight,
ScratchImage& image)
{
if ( !pDevice || IsCompressed(srcImage.format) || !IsCompressed(format) )
if (!pDevice || IsCompressed(srcImage.format) || !IsCompressed(format))
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format)
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Setup GPU compressor
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
if ( !gpubc )
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
if (!gpubc)
return E_OUTOFMEMORY;
HRESULT hr = gpubc->Initialize( pDevice );
if ( FAILED(hr) )
HRESULT hr = gpubc->Initialize(pDevice);
if (FAILED(hr))
return hr;
hr = gpubc->Prepare( srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
if ( FAILED(hr) )
hr = gpubc->Prepare(srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
if (FAILED(hr))
return hr;
// Create workspace for result
hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
}
hr = _GPUCompress( gpubc.get(), srcImage, *img, compress );
if ( FAILED(hr) )
hr = GPUCompress(gpubc.get(), srcImage, *img, compress);
if (FAILED(hr))
image.Release();
return hr;
}
_Use_decl_annotations_
HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& cImages )
HRESULT DirectX::Compress(
ID3D11Device* pDevice,
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DXGI_FORMAT format,
DWORD compress,
float alphaWeight,
ScratchImage& cImages)
{
if ( !pDevice || !srcImages || !nimages )
if (!pDevice || !srcImages || !nimages)
return E_INVALIDARG;
if ( IsCompressed(metadata.format) || !IsCompressed(format) )
if (IsCompressed(metadata.format) || !IsCompressed(format))
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format)
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
cImages.Release();
// Setup GPU compressor
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
if ( !gpubc )
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
if (!gpubc)
return E_OUTOFMEMORY;
HRESULT hr = gpubc->Initialize( pDevice );
if ( FAILED(hr) )
HRESULT hr = gpubc->Initialize(pDevice);
if (FAILED(hr))
return hr;
// Create workspace for result
TexMetadata mdata2 = metadata;
mdata2.format = format;
hr = cImages.Initialize( mdata2 );
if ( FAILED(hr) )
hr = cImages.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != cImages.GetImageCount() )
if (nimages != cImages.GetImageCount())
{
cImages.Release();
return E_FAIL;
}
const Image* dest = cImages.GetImages();
if ( !dest )
if (!dest)
{
cImages.Release();
return E_POINTER;
}
// Process images (ordered by size)
switch( metadata.dimension )
switch (metadata.dimension)
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
@ -293,46 +318,46 @@ HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages,
size_t w = metadata.width;
size_t h = metadata.height;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
if ( FAILED(hr) )
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
if (FAILED(hr))
{
cImages.Release();
return hr;
}
for( size_t item = 0; item < metadata.arraySize; ++item )
for (size_t item = 0; item < metadata.arraySize; ++item)
{
size_t index = metadata.ComputeIndex( level, item, 0 );
if ( index >= nimages )
size_t index = metadata.ComputeIndex(level, item, 0);
if (index >= nimages)
{
cImages.Release();
return E_FAIL;
}
assert( dest[ index ].format == format );
assert(dest[index].format == format);
const Image& src = srcImages[ index ];
const Image& src = srcImages[index];
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
if (src.width != dest[index].width || src.height != dest[index].height)
{
cImages.Release();
return E_FAIL;
}
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
if ( FAILED(hr) )
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
if (FAILED(hr))
{
cImages.Release();
return hr;
}
}
if ( h > 1 )
if (h > 1)
h >>= 1;
if ( w > 1 )
if (w > 1)
w >>= 1;
}
}
@ -344,59 +369,57 @@ HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages,
size_t h = metadata.height;
size_t d = metadata.depth;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
if ( FAILED(hr) )
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
if (FAILED(hr))
{
cImages.Release();
return hr;
}
for( size_t slice=0; slice < d; ++slice )
for (size_t slice = 0; slice < d; ++slice)
{
size_t index = metadata.ComputeIndex( level, 0, slice );
if ( index >= nimages )
size_t index = metadata.ComputeIndex(level, 0, slice);
if (index >= nimages)
{
cImages.Release();
return E_FAIL;
}
assert( dest[ index ].format == format );
assert(dest[index].format == format);
const Image& src = srcImages[ index ];
const Image& src = srcImages[index];
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
if (src.width != dest[index].width || src.height != dest[index].height)
{
cImages.Release();
return E_FAIL;
}
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
if ( FAILED(hr) )
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
if (FAILED(hr))
{
cImages.Release();
return hr;
}
}
if ( h > 1 )
if (h > 1)
h >>= 1;
if ( w > 1 )
if (w > 1)
w >>= 1;
if ( d > 1 )
if (d > 1)
d >>= 1;
}
}
break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
return S_OK;
}
}; // namespace

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,110 +15,117 @@
#include "directxtexp.h"
using namespace DirectX;
using Microsoft::WRL::ComPtr;
namespace DirectX
namespace
{
//-------------------------------------------------------------------------------------
// Do flip/rotate operation using WIC
//-------------------------------------------------------------------------------------
static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWORD flags,
_In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
{
if ( !srcImage.pixels || !destImage.pixels )
//-------------------------------------------------------------------------------------
// Do flip/rotate operation using WIC
//-------------------------------------------------------------------------------------
HRESULT PerformFlipRotateUsingWIC(
const Image& srcImage,
DWORD flags,
const WICPixelFormatGUID& pfGUID,
const Image& destImage)
{
if (!srcImage.pixels || !destImage.pixels)
return E_POINTER;
assert( srcImage.format == destImage.format );
assert(srcImage.format == destImage.format);
bool iswic2 = false;
IWICImagingFactory* pWIC = GetWICFactory(iswic2);
if ( !pWIC )
if (!pWIC)
return E_NOINTERFACE;
ComPtr<IWICBitmap> source;
HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
srcImage.pixels, source.GetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pWIC->CreateBitmapFromMemory(static_cast<UINT>(srcImage.width), static_cast<UINT>(srcImage.height), pfGUID,
static_cast<UINT>(srcImage.rowPitch), static_cast<UINT>(srcImage.slicePitch),
srcImage.pixels, source.GetAddressOf());
if (FAILED(hr))
return hr;
ComPtr<IWICBitmapFlipRotator> FR;
hr = pWIC->CreateBitmapFlipRotator( FR.GetAddressOf() );
if ( FAILED(hr) )
hr = pWIC->CreateBitmapFlipRotator(FR.GetAddressOf());
if (FAILED(hr))
return hr;
hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) );
if ( FAILED(hr) )
hr = FR->Initialize(source.Get(), static_cast<WICBitmapTransformOptions>(flags));
if (FAILED(hr))
return hr;
WICPixelFormatGUID pfFR;
hr = FR->GetPixelFormat( &pfFR );
if ( FAILED(hr) )
hr = FR->GetPixelFormat(&pfFR);
if (FAILED(hr))
return hr;
if ( memcmp( &pfFR, &pfGUID, sizeof(GUID) ) != 0 )
if (memcmp(&pfFR, &pfGUID, sizeof(GUID)) != 0)
{
// Flip/rotate should return the same format as the source...
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
UINT nwidth, nheight;
hr = FR->GetSize( &nwidth, &nheight );
if ( FAILED(hr) )
hr = FR->GetSize(&nwidth, &nheight);
if (FAILED(hr))
return hr;
if ( destImage.width != nwidth || destImage.height != nheight )
if (destImage.width != nwidth || destImage.height != nheight)
return E_FAIL;
hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
if ( FAILED(hr) )
hr = FR->CopyPixels(0, static_cast<UINT>(destImage.rowPitch), static_cast<UINT>(destImage.slicePitch), destImage.pixels);
if (FAILED(hr))
return hr;
return S_OK;
}
}
//-------------------------------------------------------------------------------------
// Do conversion, flip/rotate using WIC, conversion cycle
//-------------------------------------------------------------------------------------
static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
{
if ( !srcImage.pixels || !destImage.pixels )
//-------------------------------------------------------------------------------------
// Do conversion, flip/rotate using WIC, conversion cycle
//-------------------------------------------------------------------------------------
HRESULT PerformFlipRotateViaF32(
const Image& srcImage,
DWORD flags,
const Image& destImage)
{
if (!srcImage.pixels || !destImage.pixels)
return E_POINTER;
assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
assert( srcImage.format == destImage.format );
assert(srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT);
assert(srcImage.format == destImage.format);
ScratchImage temp;
HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
if ( FAILED(hr) )
HRESULT hr = _ConvertToR32G32B32A32(srcImage, temp);
if (FAILED(hr))
return hr;
const Image *tsrc = temp.GetImage( 0, 0, 0 );
if ( !tsrc )
const Image *tsrc = temp.GetImage(0, 0, 0);
if (!tsrc)
return E_POINTER;
ScratchImage rtemp;
hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
if ( FAILED(hr) )
hr = rtemp.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *tdest = rtemp.GetImage( 0, 0, 0 );
if ( !tdest )
const Image *tdest = rtemp.GetImage(0, 0, 0);
if (!tdest)
return E_POINTER;
hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
if ( FAILED(hr) )
hr = PerformFlipRotateUsingWIC(*tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest);
if (FAILED(hr))
return hr;
temp.Release();
hr = _ConvertFromR32G32B32A32( *tdest, destImage );
if ( FAILED(hr) )
hr = _ConvertFromR32G32B32A32(*tdest, destImage);
if (FAILED(hr))
return hr;
return S_OK;
}
}
@ -130,32 +137,35 @@ static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD
// Flip/rotate image
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
HRESULT DirectX::FlipRotate(
const Image& srcImage,
DWORD flags,
ScratchImage& image)
{
if ( !srcImage.pixels )
if (!srcImage.pixels)
return E_POINTER;
if ( !flags )
if (!flags)
return E_INVALIDARG;
if ( (srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX) )
if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX))
return E_INVALIDARG;
if ( IsCompressed( srcImage.format ) )
if (IsCompressed(srcImage.format))
{
// We don't support flip/rotate operations on compressed images
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
static_assert(TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC");
static_assert(TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC");
static_assert(TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC");
static_assert(TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC");
static_assert(TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC");
static_assert(TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC");
// Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270))
{
case 0:
case TEX_FR_ROTATE90:
@ -170,33 +180,33 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
size_t nwidth = srcImage.width;
size_t nheight = srcImage.height;
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
{
nwidth = srcImage.height;
nheight = srcImage.width;
}
HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(srcImage.format, nwidth, nheight, 1, 1);
if (FAILED(hr))
return hr;
const Image *rimage = image.GetImage( 0, 0, 0 );
if ( !rimage )
const Image *rimage = image.GetImage(0, 0, 0);
if (!rimage)
return E_POINTER;
WICPixelFormatGUID pfGUID;
if ( _DXGIToWIC( srcImage.format, pfGUID ) )
if (_DXGIToWIC(srcImage.format, pfGUID))
{
// Case 1: Source format is supported by Windows Imaging Component
hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage );
hr = PerformFlipRotateUsingWIC(srcImage, flags, pfGUID, *rimage);
}
else
{
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
hr = _PerformFlipRotateViaF32( srcImage, flags, *rimage );
hr = PerformFlipRotateViaF32(srcImage, flags, *rimage);
}
if ( FAILED(hr) )
if (FAILED(hr))
{
image.Release();
return hr;
@ -210,27 +220,31 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
// Flip/rotate image (complex)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD flags, ScratchImage& result )
HRESULT DirectX::FlipRotate(
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DWORD flags,
ScratchImage& result)
{
if ( !srcImages || !nimages )
if (!srcImages || !nimages)
return E_INVALIDARG;
if ( IsCompressed( metadata.format ) )
if (IsCompressed(metadata.format))
{
// We don't support flip/rotate operations on compressed images
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
static_assert(TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC");
static_assert(TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC");
static_assert(TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC");
static_assert(TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC");
static_assert(TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC");
static_assert(TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC");
// Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270))
{
case 0:
case TEX_FR_ROTATE90:
@ -245,51 +259,51 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
TexMetadata mdata2 = metadata;
bool flipwh = false;
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
{
flipwh = true;
mdata2.width = metadata.height;
mdata2.height = metadata.width;
}
HRESULT hr = result.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = result.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != result.GetImageCount() )
if (nimages != result.GetImageCount())
{
result.Release();
return E_FAIL;
}
const Image* dest = result.GetImages();
if ( !dest )
if (!dest)
{
result.Release();
return E_POINTER;
}
WICPixelFormatGUID pfGUID;
bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
bool wicpf = _DXGIToWIC(metadata.format, pfGUID);
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
const Image& src = srcImages[ index ];
if ( src.format != metadata.format )
const Image& src = srcImages[index];
if (src.format != metadata.format)
{
result.Release();
return E_FAIL;
}
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
return E_FAIL;
const Image& dst = dest[ index ];
assert( dst.format == metadata.format );
const Image& dst = dest[index];
assert(dst.format == metadata.format);
if ( flipwh )
if (flipwh)
{
if ( src.width != dst.height || src.height != dst.width )
if (src.width != dst.height || src.height != dst.width)
{
result.Release();
return E_FAIL;
@ -297,7 +311,7 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
}
else
{
if ( src.width != dst.width || src.height != dst.height )
if (src.width != dst.width || src.height != dst.height)
{
result.Release();
return E_FAIL;
@ -307,15 +321,15 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
if (wicpf)
{
// Case 1: Source format is supported by Windows Imaging Component
hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst );
hr = PerformFlipRotateUsingWIC(src, flags, pfGUID, dst);
}
else
{
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
hr = _PerformFlipRotateViaF32( src, flags, dst );
hr = PerformFlipRotateViaF32(src, flags, dst);
}
if ( FAILED(hr) )
if (FAILED(hr))
{
result.Release();
return hr;
@ -324,5 +338,3 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
return S_OK;
}
}; // namespace

View File

@ -17,46 +17,51 @@
namespace DirectX
{
extern bool _CalculateMipLevels(_In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels);
extern bool _CalculateMipLevels3D(_In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels);
extern bool _IsAlphaAllOpaqueBC(_In_ const Image& cImage);
}
extern bool _CalculateMipLevels( _In_ size_t width, _In_ size_t height, _Inout_ size_t& mipLevels );
extern bool _CalculateMipLevels3D( _In_ size_t width, _In_ size_t height, _In_ size_t depth, _Inout_ size_t& mipLevels );
extern bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage );
using namespace DirectX;
//-------------------------------------------------------------------------------------
// Determines number of image array entries and pixel size
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
size_t& nImages, size_t& pixelSize )
void DirectX::_DetermineImageArray(
const TexMetadata& metadata,
DWORD cpFlags,
size_t& nImages,
size_t& pixelSize)
{
assert( metadata.width > 0 && metadata.height > 0 && metadata.depth > 0 );
assert( metadata.arraySize > 0 );
assert( metadata.mipLevels > 0 );
assert(metadata.width > 0 && metadata.height > 0 && metadata.depth > 0);
assert(metadata.arraySize > 0);
assert(metadata.mipLevels > 0);
size_t _pixelSize = 0;
size_t _nimages = 0;
switch( metadata.dimension )
switch (metadata.dimension)
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
for( size_t item = 0; item < metadata.arraySize; ++item )
for (size_t item = 0; item < metadata.arraySize; ++item)
{
size_t w = metadata.width;
size_t h = metadata.height;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
_pixelSize += slicePitch;
++_nimages;
if ( h > 1 )
if (h > 1)
h >>= 1;
if ( w > 1 )
if (w > 1)
w >>= 1;
}
}
@ -68,31 +73,31 @@ void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
size_t h = metadata.height;
size_t d = metadata.depth;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
for( size_t slice=0; slice < d; ++slice )
for (size_t slice = 0; slice < d; ++slice)
{
_pixelSize += slicePitch;
++_nimages;
}
if ( h > 1 )
if (h > 1)
h >>= 1;
if ( w > 1 )
if (w > 1)
w >>= 1;
if ( d > 1 )
if (d > 1)
d >>= 1;
}
}
break;
default:
assert( false );
assert(false);
break;
}
@ -105,22 +110,26 @@ void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
// Fills in the image array entries
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
const TexMetadata& metadata, DWORD cpFlags,
Image* images, size_t nImages )
bool DirectX::_SetupImageArray(
uint8_t *pMemory,
size_t pixelSize,
const TexMetadata& metadata,
DWORD cpFlags,
Image* images,
size_t nImages)
{
assert( pMemory );
assert( pixelSize > 0 );
assert( nImages > 0 );
assert(pMemory);
assert(pixelSize > 0);
assert(nImages > 0);
if ( !images )
if (!images)
return false;
size_t index = 0;
uint8_t* pixels = pMemory;
const uint8_t* pEndBits = pMemory + pixelSize;
switch( metadata.dimension )
switch (metadata.dimension)
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
@ -129,20 +138,20 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
return false;
}
for( size_t item = 0; item < metadata.arraySize; ++item )
for (size_t item = 0; item < metadata.arraySize; ++item)
{
size_t w = metadata.width;
size_t h = metadata.height;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
if ( index >= nImages )
if (index >= nImages)
{
return false;
}
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
images[index].width = w;
images[index].height = h;
@ -153,15 +162,15 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
++index;
pixels += slicePitch;
if ( pixels > pEndBits )
if (pixels > pEndBits)
{
return false;
}
if ( h > 1 )
if (h > 1)
h >>= 1;
if ( w > 1 )
if (w > 1)
w >>= 1;
}
}
@ -178,14 +187,14 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
size_t h = metadata.height;
size_t d = metadata.depth;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
size_t rowPitch, slicePitch;
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
for( size_t slice=0; slice < d; ++slice )
for (size_t slice = 0; slice < d; ++slice)
{
if ( index >= nImages )
if (index >= nImages)
{
return false;
}
@ -201,19 +210,19 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
++index;
pixels += slicePitch;
if ( pixels > pEndBits )
if (pixels > pEndBits)
{
return false;
}
}
if ( h > 1 )
if (h > 1)
h >>= 1;
if ( w > 1 )
if (w > 1)
w >>= 1;
if ( d > 1 )
if (d > 1)
d >>= 1;
}
}
@ -231,20 +240,20 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
{
if ( this != &moveFrom )
if (this != &moveFrom)
{
Release();
_nimages = moveFrom._nimages;
_size = moveFrom._size;
_metadata = moveFrom._metadata;
_image = moveFrom._image;
_memory = moveFrom._memory;
m_nimages = moveFrom.m_nimages;
m_size = moveFrom.m_size;
m_metadata = moveFrom.m_metadata;
m_image = moveFrom.m_image;
m_memory = moveFrom.m_memory;
moveFrom._nimages = 0;
moveFrom._size = 0;
moveFrom._image = nullptr;
moveFrom._memory = nullptr;
moveFrom.m_nimages = 0;
moveFrom.m_size = 0;
moveFrom.m_image = nullptr;
moveFrom.m_memory = nullptr;
}
return *this;
}
@ -254,82 +263,82 @@ ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
// Methods
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT ScratchImage::Initialize( const TexMetadata& mdata, DWORD flags )
HRESULT ScratchImage::Initialize(const TexMetadata& mdata, DWORD flags)
{
if ( !IsValid(mdata.format) )
if (!IsValid(mdata.format))
return E_INVALIDARG;
if ( IsPalettized(mdata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsPalettized(mdata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
size_t mipLevels = mdata.mipLevels;
switch( mdata.dimension )
switch (mdata.dimension)
{
case TEX_DIMENSION_TEXTURE1D:
if ( !mdata.width || mdata.height != 1 || mdata.depth != 1 || !mdata.arraySize )
if (!mdata.width || mdata.height != 1 || mdata.depth != 1 || !mdata.arraySize)
return E_INVALIDARG;
if ( !_CalculateMipLevels(mdata.width,1,mipLevels) )
if (!_CalculateMipLevels(mdata.width, 1, mipLevels))
return E_INVALIDARG;
break;
case TEX_DIMENSION_TEXTURE2D:
if ( !mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize )
if (!mdata.width || !mdata.height || mdata.depth != 1 || !mdata.arraySize)
return E_INVALIDARG;
if ( mdata.IsCubemap() )
if (mdata.IsCubemap())
{
if ( (mdata.arraySize % 6) != 0 )
if ((mdata.arraySize % 6) != 0)
return E_INVALIDARG;
}
if ( !_CalculateMipLevels(mdata.width,mdata.height,mipLevels) )
if (!_CalculateMipLevels(mdata.width, mdata.height, mipLevels))
return E_INVALIDARG;
break;
case TEX_DIMENSION_TEXTURE3D:
if ( !mdata.width || !mdata.height || !mdata.depth || mdata.arraySize != 1 )
if (!mdata.width || !mdata.height || !mdata.depth || mdata.arraySize != 1)
return E_INVALIDARG;
if ( !_CalculateMipLevels3D(mdata.width,mdata.height,mdata.depth,mipLevels) )
if (!_CalculateMipLevels3D(mdata.width, mdata.height, mdata.depth, mipLevels))
return E_INVALIDARG;
break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
Release();
_metadata.width = mdata.width;
_metadata.height = mdata.height;
_metadata.depth = mdata.depth;
_metadata.arraySize = mdata.arraySize;
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = mdata.miscFlags;
_metadata.miscFlags2 = mdata.miscFlags2;
_metadata.format = mdata.format;
_metadata.dimension = mdata.dimension;
m_metadata.width = mdata.width;
m_metadata.height = mdata.height;
m_metadata.depth = mdata.depth;
m_metadata.arraySize = mdata.arraySize;
m_metadata.mipLevels = mipLevels;
m_metadata.miscFlags = mdata.miscFlags;
m_metadata.miscFlags2 = mdata.miscFlags2;
m_metadata.format = mdata.format;
m_metadata.dimension = mdata.dimension;
size_t pixelSize, nimages;
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
_image = new (std::nothrow) Image[ nimages ];
if ( !_image )
m_image = new (std::nothrow) Image[nimages];
if (!m_image)
return E_OUTOFMEMORY;
_nimages = nimages;
memset( _image, 0, sizeof(Image) * nimages );
m_nimages = nimages;
memset(m_image, 0, sizeof(Image) * nimages);
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
if ( !_memory )
m_memory = reinterpret_cast<uint8_t*>(_aligned_malloc(pixelSize, 16));
if (!m_memory)
{
Release();
return E_OUTOFMEMORY;
}
_size = pixelSize;
if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
m_size = pixelSize;
if (!_SetupImageArray(m_memory, pixelSize, m_metadata, flags, m_image, nimages))
{
Release();
return E_FAIL;
@ -339,63 +348,63 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata, DWORD flags )
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize1D( DXGI_FORMAT fmt, size_t length, size_t arraySize, size_t mipLevels, DWORD flags )
HRESULT ScratchImage::Initialize1D(DXGI_FORMAT fmt, size_t length, size_t arraySize, size_t mipLevels, DWORD flags)
{
if ( !length || !arraySize )
if (!length || !arraySize)
return E_INVALIDARG;
// 1D is a special case of the 2D case
HRESULT hr = Initialize2D( fmt, length, 1, arraySize, mipLevels, flags );
if ( FAILED(hr) )
HRESULT hr = Initialize2D(fmt, length, 1, arraySize, mipLevels, flags);
if (FAILED(hr))
return hr;
_metadata.dimension = TEX_DIMENSION_TEXTURE1D;
m_metadata.dimension = TEX_DIMENSION_TEXTURE1D;
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height, size_t arraySize, size_t mipLevels, DWORD flags )
HRESULT ScratchImage::Initialize2D(DXGI_FORMAT fmt, size_t width, size_t height, size_t arraySize, size_t mipLevels, DWORD flags)
{
if ( !IsValid(fmt) || !width || !height || !arraySize )
if (!IsValid(fmt) || !width || !height || !arraySize)
return E_INVALIDARG;
if ( IsPalettized(fmt) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsPalettized(fmt))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( !_CalculateMipLevels(width,height,mipLevels) )
if (!_CalculateMipLevels(width, height, mipLevels))
return E_INVALIDARG;
Release();
_metadata.width = width;
_metadata.height = height;
_metadata.depth = 1;
_metadata.arraySize = arraySize;
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0;
_metadata.miscFlags2 = 0;
_metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE2D;
m_metadata.width = width;
m_metadata.height = height;
m_metadata.depth = 1;
m_metadata.arraySize = arraySize;
m_metadata.mipLevels = mipLevels;
m_metadata.miscFlags = 0;
m_metadata.miscFlags2 = 0;
m_metadata.format = fmt;
m_metadata.dimension = TEX_DIMENSION_TEXTURE2D;
size_t pixelSize, nimages;
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
_image = new (std::nothrow) Image[ nimages ];
if ( !_image )
m_image = new (std::nothrow) Image[nimages];
if (!m_image)
return E_OUTOFMEMORY;
_nimages = nimages;
memset( _image, 0, sizeof(Image) * nimages );
m_nimages = nimages;
memset(m_image, 0, sizeof(Image) * nimages);
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
if ( !_memory )
m_memory = reinterpret_cast<uint8_t*>(_aligned_malloc(pixelSize, 16));
if (!m_memory)
{
Release();
return E_OUTOFMEMORY;
}
_size = pixelSize;
if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
m_size = pixelSize;
if (!_SetupImageArray(m_memory, pixelSize, m_metadata, flags, m_image, nimages))
{
Release();
return E_FAIL;
@ -405,50 +414,50 @@ HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height, size_t depth, size_t mipLevels, DWORD flags )
HRESULT ScratchImage::Initialize3D(DXGI_FORMAT fmt, size_t width, size_t height, size_t depth, size_t mipLevels, DWORD flags)
{
if ( !IsValid(fmt) || !width || !height || !depth )
if (!IsValid(fmt) || !width || !height || !depth)
return E_INVALIDARG;
if ( IsPalettized(fmt) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsPalettized(fmt))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( !_CalculateMipLevels3D(width,height,depth,mipLevels) )
if (!_CalculateMipLevels3D(width, height, depth, mipLevels))
return E_INVALIDARG;
Release();
_metadata.width = width;
_metadata.height = height;
_metadata.depth = depth;
_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
_metadata.mipLevels = mipLevels;
_metadata.miscFlags = 0;
_metadata.miscFlags2 = 0;
_metadata.format = fmt;
_metadata.dimension = TEX_DIMENSION_TEXTURE3D;
m_metadata.width = width;
m_metadata.height = height;
m_metadata.depth = depth;
m_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
m_metadata.mipLevels = mipLevels;
m_metadata.miscFlags = 0;
m_metadata.miscFlags2 = 0;
m_metadata.format = fmt;
m_metadata.dimension = TEX_DIMENSION_TEXTURE3D;
size_t pixelSize, nimages;
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
_image = new (std::nothrow) Image[ nimages ];
if ( !_image )
m_image = new (std::nothrow) Image[nimages];
if (!m_image)
{
Release();
return E_OUTOFMEMORY;
}
_nimages = nimages;
memset( _image, 0, sizeof(Image) * nimages );
m_nimages = nimages;
memset(m_image, 0, sizeof(Image) * nimages);
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
if ( !_memory )
m_memory = reinterpret_cast<uint8_t*>(_aligned_malloc(pixelSize, 16));
if (!m_memory)
{
Release();
return E_OUTOFMEMORY;
}
_size = pixelSize;
m_size = pixelSize;
if ( !_SetupImageArray( _memory, pixelSize, _metadata, flags, _image, nimages ) )
if (!_SetupImageArray(m_memory, pixelSize, m_metadata, flags, m_image, nimages))
{
Release();
return E_FAIL;
@ -458,51 +467,51 @@ HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeCube( DXGI_FORMAT fmt, size_t width, size_t height, size_t nCubes, size_t mipLevels, DWORD flags )
HRESULT ScratchImage::InitializeCube(DXGI_FORMAT fmt, size_t width, size_t height, size_t nCubes, size_t mipLevels, DWORD flags)
{
if ( !width || !height || !nCubes )
if (!width || !height || !nCubes)
return E_INVALIDARG;
// A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
HRESULT hr = Initialize2D( fmt, width, height, nCubes * 6, mipLevels, flags );
if ( FAILED(hr) )
HRESULT hr = Initialize2D(fmt, width, height, nCubes * 6, mipLevels, flags);
if (FAILED(hr))
return hr;
_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
m_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeFromImage( const Image& srcImage, bool allow1D, DWORD flags )
HRESULT ScratchImage::InitializeFromImage(const Image& srcImage, bool allow1D, DWORD flags)
{
HRESULT hr = ( srcImage.height > 1 || !allow1D )
? Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1, flags )
: Initialize1D( srcImage.format, srcImage.width, 1, 1, flags );
HRESULT hr = (srcImage.height > 1 || !allow1D)
? Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1, flags)
: Initialize1D(srcImage.format, srcImage.width, 1, 1, flags);
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
size_t rowCount = ComputeScanlines( srcImage.format, srcImage.height );
if ( !rowCount )
size_t rowCount = ComputeScanlines(srcImage.format, srcImage.height);
if (!rowCount)
return E_UNEXPECTED;
const uint8_t* sptr = reinterpret_cast<const uint8_t*>( srcImage.pixels );
if ( !sptr )
const uint8_t* sptr = reinterpret_cast<const uint8_t*>(srcImage.pixels);
if (!sptr)
return E_POINTER;
auto dptr = reinterpret_cast<uint8_t*>( _image[0].pixels );
if ( !dptr )
auto dptr = reinterpret_cast<uint8_t*>(m_image[0].pixels);
if (!dptr)
return E_POINTER;
size_t spitch = srcImage.rowPitch;
size_t dpitch = _image[0].rowPitch;
size_t dpitch = m_image[0].rowPitch;
size_t size = std::min<size_t>( dpitch, spitch );
size_t size = std::min<size_t>(dpitch, spitch);
for( size_t y = 0; y < rowCount; ++y )
for (size_t y = 0; y < rowCount; ++y)
{
memcpy_s( dptr, dpitch, sptr, size );
memcpy_s(dptr, dpitch, sptr, size);
sptr += spitch;
dptr += dpitch;
}
@ -511,57 +520,57 @@ HRESULT ScratchImage::InitializeFromImage( const Image& srcImage, bool allow1D,
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nImages, bool allow1D, DWORD flags )
HRESULT ScratchImage::InitializeArrayFromImages(const Image* images, size_t nImages, bool allow1D, DWORD flags)
{
if ( !images || !nImages )
if (!images || !nImages)
return E_INVALIDARG;
DXGI_FORMAT format = images[0].format;
size_t width = images[0].width;
size_t height = images[0].height;
for( size_t index=0; index < nImages; ++index )
for (size_t index = 0; index < nImages; ++index)
{
if ( !images[index].pixels )
if (!images[index].pixels)
return E_POINTER;
if ( images[index].format != format || images[index].width != width || images[index].height != height )
if (images[index].format != format || images[index].width != width || images[index].height != height)
{
// All images must be the same format, width, and height
return E_FAIL;
}
}
HRESULT hr = ( height > 1 || !allow1D )
? Initialize2D( format, width, height, nImages, 1, flags )
: Initialize1D( format, width, nImages, 1, flags );
HRESULT hr = (height > 1 || !allow1D)
? Initialize2D(format, width, height, nImages, 1, flags)
: Initialize1D(format, width, nImages, 1, flags);
if ( FAILED(hr) )
if (FAILED(hr))
return hr;
size_t rowCount = ComputeScanlines( format, height );
if ( !rowCount )
size_t rowCount = ComputeScanlines(format, height);
if (!rowCount)
return E_UNEXPECTED;
for( size_t index=0; index < nImages; ++index )
for (size_t index = 0; index < nImages; ++index)
{
auto sptr = reinterpret_cast<const uint8_t*>( images[index].pixels );
if ( !sptr )
auto sptr = reinterpret_cast<const uint8_t*>(images[index].pixels);
if (!sptr)
return E_POINTER;
assert( index < _nimages );
auto dptr = reinterpret_cast<uint8_t*>( _image[index].pixels );
if ( !dptr )
assert(index < m_nimages);
auto dptr = reinterpret_cast<uint8_t*>(m_image[index].pixels);
if (!dptr)
return E_POINTER;
size_t spitch = images[index].rowPitch;
size_t dpitch = _image[index].rowPitch;
size_t dpitch = m_image[index].rowPitch;
size_t size = std::min<size_t>( dpitch, spitch );
size_t size = std::min<size_t>(dpitch, spitch);
for( size_t y = 0; y < rowCount; ++y )
for (size_t y = 0; y < rowCount; ++y)
{
memcpy_s( dptr, dpitch, sptr, size );
memcpy_s(dptr, dpitch, sptr, size);
sptr += spitch;
dptr += dpitch;
}
@ -571,73 +580,73 @@ HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nIm
}
_Use_decl_annotations_
HRESULT ScratchImage::InitializeCubeFromImages( const Image* images, size_t nImages, DWORD flags )
HRESULT ScratchImage::InitializeCubeFromImages(const Image* images, size_t nImages, DWORD flags)
{
if ( !images || !nImages )
if (!images || !nImages)
return E_INVALIDARG;
// A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
if ( ( nImages % 6 ) != 0 )
if ((nImages % 6) != 0)
return E_INVALIDARG;
HRESULT hr = InitializeArrayFromImages( images, nImages, false, flags );
if ( FAILED(hr) )
HRESULT hr = InitializeArrayFromImages(images, nImages, false, flags);
if (FAILED(hr))
return hr;
_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
m_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
return S_OK;
}
_Use_decl_annotations_
HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth, DWORD flags )
HRESULT ScratchImage::Initialize3DFromImages(const Image* images, size_t depth, DWORD flags)
{
if ( !images || !depth )
if (!images || !depth)
return E_INVALIDARG;
DXGI_FORMAT format = images[0].format;
size_t width = images[0].width;
size_t height = images[0].height;
for( size_t slice=0; slice < depth; ++slice )
for (size_t slice = 0; slice < depth; ++slice)
{
if ( !images[slice].pixels )
if (!images[slice].pixels)
return E_POINTER;
if ( images[slice].format != format || images[slice].width != width || images[slice].height != height )
if (images[slice].format != format || images[slice].width != width || images[slice].height != height)
{
// All images must be the same format, width, and height
return E_FAIL;
}
}
HRESULT hr = Initialize3D( format, width, height, depth, 1, flags );
if ( FAILED(hr) )
HRESULT hr = Initialize3D(format, width, height, depth, 1, flags);
if (FAILED(hr))
return hr;
size_t rowCount = ComputeScanlines( format, height );
if ( !rowCount )
size_t rowCount = ComputeScanlines(format, height);
if (!rowCount)
return E_UNEXPECTED;
for( size_t slice=0; slice < depth; ++slice )
for (size_t slice = 0; slice < depth; ++slice)
{
auto sptr = reinterpret_cast<const uint8_t*>( images[slice].pixels );
if ( !sptr )
auto sptr = reinterpret_cast<const uint8_t*>(images[slice].pixels);
if (!sptr)
return E_POINTER;
assert( slice < _nimages );
auto dptr = reinterpret_cast<uint8_t*>( _image[slice].pixels );
if ( !dptr )
assert(slice < m_nimages);
auto dptr = reinterpret_cast<uint8_t*>(m_image[slice].pixels);
if (!dptr)
return E_POINTER;
size_t spitch = images[slice].rowPitch;
size_t dpitch = _image[slice].rowPitch;
size_t dpitch = m_image[slice].rowPitch;
size_t size = std::min<size_t>( dpitch, spitch );
size_t size = std::min<size_t>(dpitch, spitch);
for( size_t y = 0; y < rowCount; ++y )
for (size_t y = 0; y < rowCount; ++y)
{
memcpy_s( dptr, dpitch, sptr, size );
memcpy_s(dptr, dpitch, sptr, size);
sptr += spitch;
dptr += dpitch;
}
@ -648,39 +657,39 @@ HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth,
void ScratchImage::Release()
{
_nimages = 0;
_size = 0;
m_nimages = 0;
m_size = 0;
if ( _image )
if (m_image)
{
delete [] _image;
_image = 0;
delete[] m_image;
m_image = nullptr;
}
if ( _memory )
if (m_memory)
{
_aligned_free( _memory );
_memory = 0;
_aligned_free(m_memory);
m_memory = nullptr;
}
memset(&_metadata, 0, sizeof(_metadata));
memset(&m_metadata, 0, sizeof(m_metadata));
}
_Use_decl_annotations_
bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
bool ScratchImage::OverrideFormat(DXGI_FORMAT f)
{
if ( !_image )
if (!m_image)
return false;
if ( !IsValid( f ) || IsPlanar( f ) || IsPalettized( f ) )
if (!IsValid(f) || IsPlanar(f) || IsPalettized(f))
return false;
for( size_t index = 0; index < _nimages; ++index )
for (size_t index = 0; index < m_nimages; ++index)
{
_image[ index ].format = f;
m_image[index].format = f;
}
_metadata.format = f;
m_metadata.format = f;
return true;
}
@ -688,42 +697,42 @@ bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
_Use_decl_annotations_
const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
{
if ( mip >= _metadata.mipLevels )
if (mip >= m_metadata.mipLevels)
return nullptr;
size_t index = 0;
switch( _metadata.dimension )
switch (m_metadata.dimension)
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
if ( slice > 0 )
if (slice > 0)
return nullptr;
if ( item >= _metadata.arraySize )
if (item >= m_metadata.arraySize)
return nullptr;
index = item*( _metadata.mipLevels ) + mip;
index = item*(m_metadata.mipLevels) + mip;
break;
case TEX_DIMENSION_TEXTURE3D:
if ( item > 0 )
if (item > 0)
{
// No support for arrays of volumes
return nullptr;
}
else
{
size_t d = _metadata.depth;
size_t d = m_metadata.depth;
for( size_t level = 0; level < mip; ++level )
for (size_t level = 0; level < mip; ++level)
{
index += d;
if ( d > 1 )
if (d > 1)
d >>= 1;
}
if ( slice >= d )
if (slice >= d)
return nullptr;
index += slice;
@ -734,51 +743,51 @@ const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
return nullptr;
}
return &_image[index];
return &m_image[index];
}
bool ScratchImage::IsAlphaAllOpaque() const
{
if ( !_image )
if (!m_image)
return false;
if ( !HasAlpha( _metadata.format ) )
if (!HasAlpha(m_metadata.format))
return true;
if ( IsCompressed( _metadata.format ) )
if (IsCompressed(m_metadata.format))
{
for( size_t index = 0; index < _nimages; ++index )
for (size_t index = 0; index < m_nimages; ++index)
{
if ( !_IsAlphaAllOpaqueBC( _image[ index ] ) )
if (!_IsAlphaAllOpaqueBC(m_image[index]))
return false;
}
}
else
{
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*_metadata.width), 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*m_metadata.width), 16)));
if (!scanline)
return false;
static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
for( size_t index = 0; index < _nimages; ++index )
for (size_t index = 0; index < m_nimages; ++index)
{
#pragma warning( suppress : 6011 )
const Image& img = _image[ index ];
const Image& img = m_image[index];
const uint8_t *pPixels = img.pixels;
assert( pPixels );
assert(pPixels);
for( size_t h = 0; h < img.height; ++h )
for (size_t h = 0; h < img.height; ++h)
{
if ( !_LoadScanline( scanline.get(), img.width, pPixels, img.rowPitch, img.format ) )
if (!_LoadScanline(scanline.get(), img.width, pPixels, img.rowPitch, img.format))
return false;
XMVECTOR* ptr = scanline.get();
for( size_t w = 0; w < img.width; ++w )
for (size_t w = 0; w < img.width; ++w)
{
XMVECTOR alpha = XMVectorSplatW( *ptr );
if ( XMVector4Less( alpha, threshold ) )
XMVECTOR alpha = XMVectorSplatW(*ptr);
if (XMVector4Less(alpha, threshold))
return false;
++ptr;
}
@ -790,5 +799,3 @@ bool ScratchImage::IsAlphaAllOpaque() const
return true;
}
}; // namespace

File diff suppressed because it is too large Load Diff

View File

@ -15,29 +15,34 @@
#include "directxtexp.h"
namespace DirectX
{
static const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
using namespace DirectX;
//-------------------------------------------------------------------------------------
static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
_Out_ float& mse, _Out_writes_opt_(4) float* mseV,
_In_ DWORD flags )
namespace
{
if ( !image1.pixels || !image2.pixels )
const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
//-------------------------------------------------------------------------------------
HRESULT ComputeMSE_(
const Image& image1,
const Image& image2,
float& mse,
_Out_writes_opt_(4) float* mseV,
DWORD flags)
{
if (!image1.pixels || !image2.pixels)
return E_POINTER;
assert( image1.width == image2.width && image1.height == image2.height );
assert( !IsCompressed( image1.format ) && !IsCompressed( image2.format ) );
assert(image1.width == image2.width && image1.height == image2.height);
assert(!IsCompressed(image1.format) && !IsCompressed(image2.format));
const size_t width = image1.width;
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width)*2, 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width) * 2, 16)));
if (!scanline)
return E_OUTOFMEMORY;
// Flags implied from image formats
switch( image1.format )
switch (image1.format)
{
case DXGI_FORMAT_B8G8R8X8_UNORM:
flags |= CMSE_IGNORE_ALPHA;
@ -57,7 +62,7 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
break;
}
switch( image2.format )
switch (image2.format)
{
case DXGI_FORMAT_B8G8R8X8_UNORM:
flags |= CMSE_IGNORE_ALPHA;
@ -86,58 +91,58 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
XMVECTOR acc = g_XMZero;
static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
for( size_t h = 0; h < image1.height; ++h )
for (size_t h = 0; h < image1.height; ++h)
{
XMVECTOR* ptr1 = scanline.get();
if ( !_LoadScanline( ptr1, width, pSrc1, rowPitch1, image1.format ) )
if (!_LoadScanline(ptr1, width, pSrc1, rowPitch1, image1.format))
return E_FAIL;
XMVECTOR* ptr2 = scanline.get() + width;
if ( !_LoadScanline( ptr2, width, pSrc2, rowPitch2, image2.format ) )
if (!_LoadScanline(ptr2, width, pSrc2, rowPitch2, image2.format))
return E_FAIL;
for( size_t i = 0; i < width; ++i )
for (size_t i = 0; i < width; ++i)
{
XMVECTOR v1 = *(ptr1++);
if ( flags & CMSE_IMAGE1_SRGB )
if (flags & CMSE_IMAGE1_SRGB)
{
v1 = XMVectorPow( v1, g_Gamma22 );
v1 = XMVectorPow(v1, g_Gamma22);
}
if ( flags & CMSE_IMAGE1_X2_BIAS )
if (flags & CMSE_IMAGE1_X2_BIAS)
{
v1 = XMVectorMultiplyAdd( v1, two, g_XMNegativeOne );
v1 = XMVectorMultiplyAdd(v1, two, g_XMNegativeOne);
}
XMVECTOR v2 = *(ptr2++);
if ( flags & CMSE_IMAGE2_SRGB )
if (flags & CMSE_IMAGE2_SRGB)
{
v2 = XMVectorPow( v2, g_Gamma22 );
v2 = XMVectorPow(v2, g_Gamma22);
}
if ( flags & CMSE_IMAGE2_X2_BIAS )
if (flags & CMSE_IMAGE2_X2_BIAS)
{
v1 = XMVectorMultiplyAdd( v2, two, g_XMNegativeOne );
v1 = XMVectorMultiplyAdd(v2, two, g_XMNegativeOne);
}
// sum[ (I1 - I2)^2 ]
XMVECTOR v = XMVectorSubtract( v1, v2 );
if ( flags & CMSE_IGNORE_RED )
XMVECTOR v = XMVectorSubtract(v1, v2);
if (flags & CMSE_IGNORE_RED)
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskX );
v = XMVectorSelect(v, g_XMZero, g_XMMaskX);
}
if ( flags & CMSE_IGNORE_GREEN )
if (flags & CMSE_IGNORE_GREEN)
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskY );
v = XMVectorSelect(v, g_XMZero, g_XMMaskY);
}
if ( flags & CMSE_IGNORE_BLUE )
if (flags & CMSE_IGNORE_BLUE)
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskZ );
v = XMVectorSelect(v, g_XMZero, g_XMMaskZ);
}
if ( flags & CMSE_IGNORE_ALPHA )
if (flags & CMSE_IGNORE_ALPHA)
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskW );
v = XMVectorSelect(v, g_XMZero, g_XMMaskW);
}
acc = XMVectorMultiplyAdd( v, v, acc );
acc = XMVectorMultiplyAdd(v, v, acc);
}
pSrc1 += rowPitch1;
@ -145,22 +150,23 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
}
// MSE = sum[ (I1 - I2)^2 ] / w*h
XMVECTOR d = XMVectorReplicate( float(image1.width * image1.height) );
XMVECTOR v = XMVectorDivide( acc, d );
if ( mseV )
XMVECTOR d = XMVectorReplicate(float(image1.width * image1.height));
XMVECTOR v = XMVectorDivide(acc, d);
if (mseV)
{
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( mseV ), v );
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(mseV), v);
mse = mseV[0] + mseV[1] + mseV[2] + mseV[3];
}
else
{
XMFLOAT4 _mseV;
XMStoreFloat4( &_mseV, v );
XMStoreFloat4(&_mseV, v);
mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w;
}
return S_OK;
}
}
};
//=====================================================================================
@ -171,57 +177,63 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
// Copies a rectangle from one image into another
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image& dstImage, DWORD filter, size_t xOffset, size_t yOffset )
HRESULT DirectX::CopyRectangle(
const Image& srcImage,
const Rect& srcRect,
const Image& dstImage,
DWORD filter,
size_t xOffset,
size_t yOffset)
{
if ( !srcImage.pixels || !dstImage.pixels )
if (!srcImage.pixels || !dstImage.pixels)
return E_POINTER;
if ( IsCompressed( srcImage.format ) || IsCompressed( dstImage.format )
|| IsPlanar( srcImage.format ) || IsPlanar( dstImage.format )
|| IsPalettized( srcImage.format ) || IsPalettized( dstImage.format ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsCompressed(srcImage.format) || IsCompressed(dstImage.format)
|| IsPlanar(srcImage.format) || IsPlanar(dstImage.format)
|| IsPalettized(srcImage.format) || IsPalettized(dstImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Validate rectangle/offset
if ( !srcRect.w || !srcRect.h || ( (srcRect.x + srcRect.w) > srcImage.width ) || ( (srcRect.y + srcRect.h) > srcImage.height ) )
if (!srcRect.w || !srcRect.h || ((srcRect.x + srcRect.w) > srcImage.width) || ((srcRect.y + srcRect.h) > srcImage.height))
{
return E_INVALIDARG;
}
if ( ( (xOffset + srcRect.w) > dstImage.width ) || ( (yOffset + srcRect.h) > dstImage.height ) )
if (((xOffset + srcRect.w) > dstImage.width) || ((yOffset + srcRect.h) > dstImage.height))
{
return E_INVALIDARG;
}
// Compute source bytes-per-pixel
size_t sbpp = BitsPerPixel( srcImage.format );
if ( !sbpp )
size_t sbpp = BitsPerPixel(srcImage.format);
if (!sbpp)
return E_FAIL;
if ( sbpp < 8 )
if (sbpp < 8)
{
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
const uint8_t* pEndSrc = srcImage.pixels + srcImage.rowPitch*srcImage.height;
const uint8_t* pEndDest = dstImage.pixels + dstImage.rowPitch*dstImage.height;
// Round to bytes
sbpp = ( sbpp + 7 ) / 8;
sbpp = (sbpp + 7) / 8;
const uint8_t* pSrc = srcImage.pixels + (srcRect.y * srcImage.rowPitch) + (srcRect.x * sbpp);
if ( srcImage.format == dstImage.format )
if (srcImage.format == dstImage.format)
{
// Direct copy case (avoid intermediate conversions)
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * sbpp);
const size_t copyW = srcRect.w * sbpp;
for( size_t h=0; h < srcRect.h; ++h )
for (size_t h = 0; h < srcRect.h; ++h)
{
if ( ( (pSrc+copyW) > pEndSrc ) || (pDest > pEndDest) )
if (((pSrc + copyW) > pEndSrc) || (pDest > pEndDest))
return E_FAIL;
memcpy_s( pDest, pEndDest - pDest, pSrc, copyW );
memcpy_s(pDest, pEndDest - pDest, pSrc, copyW);
pSrc += srcImage.rowPitch;
pDest += dstImage.rowPitch;
@ -231,39 +243,39 @@ HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image&
}
// Compute destination bytes-per-pixel (not the same format as source)
size_t dbpp = BitsPerPixel( dstImage.format );
if ( !dbpp )
size_t dbpp = BitsPerPixel(dstImage.format);
if (!dbpp)
return E_FAIL;
if ( dbpp < 8 )
if (dbpp < 8)
{
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
// Round to bytes
dbpp = ( dbpp + 7 ) / 8;
dbpp = (dbpp + 7) / 8;
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * dbpp);
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcRect.w), 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcRect.w), 16)));
if (!scanline)
return E_OUTOFMEMORY;
const size_t copyS = srcRect.w * sbpp;
const size_t copyD = srcRect.w * dbpp;
for( size_t h=0; h < srcRect.h; ++h )
for (size_t h = 0; h < srcRect.h; ++h)
{
if ( ( (pSrc+copyS) > pEndSrc) || ((pDest+copyD) > pEndDest) )
if (((pSrc + copyS) > pEndSrc) || ((pDest + copyD) > pEndDest))
return E_FAIL;
if ( !_LoadScanline( scanline.get(), srcRect.w, pSrc, copyS, srcImage.format ) )
if (!_LoadScanline(scanline.get(), srcRect.w, pSrc, copyS, srcImage.format))
return E_FAIL;
_ConvertScanline( scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter );
_ConvertScanline(scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter);
if ( !_StoreScanline( pDest, copyD, dstImage.format, scanline.get(), srcRect.w ) )
if (!_StoreScanline(pDest, copyD, dstImage.format, scanline.get(), srcRect.w))
return E_FAIL;
pSrc += srcImage.rowPitch;
@ -278,77 +290,80 @@ HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image&
// Computes the Mean-Squared-Error (MSE) between two images
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float* mseV, DWORD flags )
HRESULT DirectX::ComputeMSE(
const Image& image1,
const Image& image2,
float& mse,
float* mseV,
DWORD flags)
{
if ( !image1.pixels || !image2.pixels )
if (!image1.pixels || !image2.pixels)
return E_POINTER;
if ( image1.width != image2.width || image1.height != image2.height )
if (image1.width != image2.width || image1.height != image2.height)
return E_INVALIDARG;
if ( IsPlanar( image1.format ) || IsPlanar( image2.format )
|| IsPalettized( image1.format ) || IsPalettized( image2.format ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsPlanar(image1.format) || IsPlanar(image2.format)
|| IsPalettized(image1.format) || IsPalettized(image2.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( IsCompressed(image1.format) )
if (IsCompressed(image1.format))
{
if ( IsCompressed(image2.format) )
if (IsCompressed(image2.format))
{
// Case 1: both images are compressed, expand to RGBA32F
ScratchImage temp1;
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1 );
if ( FAILED(hr) )
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1);
if (FAILED(hr))
return hr;
ScratchImage temp2;
hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2 );
if ( FAILED(hr) )
hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2);
if (FAILED(hr))
return hr;
const Image* img1 = temp1.GetImage(0,0,0);
const Image* img2 = temp2.GetImage(0,0,0);
if ( !img1 || !img2 )
const Image* img1 = temp1.GetImage(0, 0, 0);
const Image* img2 = temp2.GetImage(0, 0, 0);
if (!img1 || !img2)
return E_POINTER;
return _ComputeMSE( *img1, *img2, mse, mseV, flags );
return ComputeMSE_(*img1, *img2, mse, mseV, flags);
}
else
{
// Case 2: image1 is compressed, expand to RGBA32F
ScratchImage temp;
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
if ( FAILED(hr) )
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
if (FAILED(hr))
return hr;
const Image* img = temp.GetImage(0,0,0);
if ( !img )
const Image* img = temp.GetImage(0, 0, 0);
if (!img)
return E_POINTER;
return _ComputeMSE( *img, image2, mse, mseV, flags );
return ComputeMSE_(*img, image2, mse, mseV, flags);
}
}
else
{
if ( IsCompressed(image2.format) )
if (IsCompressed(image2.format))
{
// Case 3: image2 is compressed, expand to RGBA32F
ScratchImage temp;
HRESULT hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
if ( FAILED(hr) )
HRESULT hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
if (FAILED(hr))
return hr;
const Image* img = temp.GetImage(0,0,0);
if ( !img )
const Image* img = temp.GetImage(0, 0, 0);
if (!img)
return E_POINTER;
return _ComputeMSE( image1, *img, mse, mseV, flags );
return ComputeMSE_(image1, *img, mse, mseV, flags);
}
else
{
// Case 4: neither image is compressed
return _ComputeMSE( image1, image2, mse, mseV, flags );
return ComputeMSE_(image1, image2, mse, mseV, flags);
}
}
}
}; // namespace

View File

@ -15,29 +15,31 @@
#include "directxtexp.h"
namespace DirectX
using namespace DirectX;
namespace
{
#pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
static inline float _EvaluateColor( _In_ FXMVECTOR val, _In_ DWORD flags )
{
inline float EvaluateColor(_In_ FXMVECTOR val, _In_ DWORD flags)
{
XMFLOAT4A f;
static XMVECTORF32 lScale = { 0.2125f, 0.7154f, 0.0721f, 1.f };
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
switch( flags & 0xf )
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
switch (flags & 0xf)
{
case 0:
case CNMAP_CHANNEL_RED: return XMVectorGetX( val );
case CNMAP_CHANNEL_GREEN: return XMVectorGetY( val );
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ( val );
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW( val );
case CNMAP_CHANNEL_RED: return XMVectorGetX(val);
case CNMAP_CHANNEL_GREEN: return XMVectorGetY(val);
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ(val);
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW(val);
case CNMAP_CHANNEL_LUMINANCE:
{
XMVECTOR v = XMVectorMultiply( val, lScale );
XMStoreFloat4A( &f, v );
XMVECTOR v = XMVectorMultiply(val, lScale);
XMStoreFloat4A(&f, v);
return f.x + f.y + f.z;
}
break;
@ -46,62 +48,65 @@ static inline float _EvaluateColor( _In_ FXMVECTOR val, _In_ DWORD flags )
assert(false);
return 0.f;
}
}
static void _EvaluateRow( _In_reads_(width) const XMVECTOR* pSource, _Out_writes_(width+2) float* pDest,
_In_ size_t width, _In_ DWORD flags )
{
assert( pSource && pDest );
assert( width > 0 );
for( size_t x = 0; x < width; ++x )
{
pDest[x+1] = _EvaluateColor( pSource[x], flags );
}
if ( flags & CNMAP_MIRROR_U )
void EvaluateRow(
_In_reads_(width) const XMVECTOR* pSource,
_Out_writes_(width + 2) float* pDest,
size_t width,
DWORD flags)
{
assert(pSource && pDest);
assert(width > 0);
for (size_t x = 0; x < width; ++x)
{
pDest[x + 1] = EvaluateColor(pSource[x], flags);
}
if (flags & CNMAP_MIRROR_U)
{
// Mirror in U
pDest[0] = _EvaluateColor( pSource[0], flags );
pDest[width+1] = _EvaluateColor( pSource[width-1], flags );
pDest[0] = EvaluateColor(pSource[0], flags);
pDest[width + 1] = EvaluateColor(pSource[width - 1], flags);
}
else
{
// Wrap in U
pDest[0] = _EvaluateColor( pSource[width-1], flags );
pDest[width+1] = _EvaluateColor( pSource[0], flags );
pDest[0] = EvaluateColor(pSource[width - 1], flags);
pDest[width + 1] = EvaluateColor(pSource[0], flags);
}
}
}
static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
_In_ DXGI_FORMAT format, _In_ const Image& normalMap )
{
if ( !srcImage.pixels || !normalMap.pixels )
HRESULT ComputeNMap(_In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
_In_ DXGI_FORMAT format, _In_ const Image& normalMap)
{
if (!srcImage.pixels || !normalMap.pixels)
return E_INVALIDARG;
const DWORD convFlags = _GetConvertFlags( format );
if ( !convFlags )
const DWORD convFlags = _GetConvertFlags(format);
if (!convFlags)
return E_FAIL;
if ( !( convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT) ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (!(convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT)))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
const size_t width = srcImage.width;
const size_t height = srcImage.height;
if ( width != normalMap.width || height != normalMap.height )
if (width != normalMap.width || height != normalMap.height)
return E_FAIL;
// Allocate temporary space (4 scanlines and 3 evaluated rows)
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*4), 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width * 4), 16)));
if (!scanline)
return E_OUTOFMEMORY;
ScopedAlignedArrayFloat buffer( reinterpret_cast<float*>( _aligned_malloc( ( ( sizeof(float) * ( width + 2 ) ) * 3 ), 16 ) ) );
if ( !buffer )
ScopedAlignedArrayFloat buffer(reinterpret_cast<float*>(_aligned_malloc(((sizeof(float) * (width + 2)) * 3), 16)));
if (!buffer)
return E_OUTOFMEMORY;
uint8_t* pDest = normalMap.pixels;
if ( !pDest )
if (!pDest)
return E_POINTER;
XMVECTOR* row0 = scanline.get();
@ -117,117 +122,117 @@ static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_
const uint8_t* pSrc = srcImage.pixels;
// Read first scanline row into 'row1'
if ( !_LoadScanline( row1, width, pSrc, rowPitch, srcImage.format ) )
if (!_LoadScanline(row1, width, pSrc, rowPitch, srcImage.format))
return E_FAIL;
// Setup 'row0'
if ( flags & CNMAP_MIRROR_V )
if (flags & CNMAP_MIRROR_V)
{
// Mirror first row
memcpy_s( row0, rowPitch, row1, rowPitch );
memcpy_s(row0, rowPitch, row1, rowPitch);
}
else
{
// Read last row (Wrap V)
if ( !_LoadScanline( row0, width, pSrc + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
if (!_LoadScanline(row0, width, pSrc + (rowPitch * (height - 1)), rowPitch, srcImage.format))
return E_FAIL;
}
// Evaluate the initial rows
_EvaluateRow( row0, val0, width, flags );
_EvaluateRow( row1, val1, width, flags );
EvaluateRow(row0, val0, width, flags);
EvaluateRow(row1, val1, width, flags);
pSrc += rowPitch;
for( size_t y = 0; y < height; ++y )
for (size_t y = 0; y < height; ++y)
{
// Load next scanline of source image
if ( y < (height-1) )
if (y < (height - 1))
{
if ( !_LoadScanline( row2, width, pSrc, rowPitch, srcImage.format ) )
if (!_LoadScanline(row2, width, pSrc, rowPitch, srcImage.format))
return E_FAIL;
}
else
{
if ( flags & CNMAP_MIRROR_V )
if (flags & CNMAP_MIRROR_V)
{
// Use last row of source image
if ( !_LoadScanline( row2, width, srcImage.pixels + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
if (!_LoadScanline(row2, width, srcImage.pixels + (rowPitch * (height - 1)), rowPitch, srcImage.format))
return E_FAIL;
}
else
{
// Use first row of source image (Wrap V)
if ( !_LoadScanline( row2, width, srcImage.pixels, rowPitch, srcImage.format ) )
if (!_LoadScanline(row2, width, srcImage.pixels, rowPitch, srcImage.format))
return E_FAIL;
}
}
// Evaluate row
_EvaluateRow( row2, val2, width, flags );
EvaluateRow(row2, val2, width, flags);
// Generate target scanline
XMVECTOR *dptr = target;
for( size_t x = 0; x < width; ++x )
for (size_t x = 0; x < width; ++x)
{
// Compute normal via central differencing
float totDelta = ( val0[x] - val0[x+2] ) + ( val1[x] - val1[x+2] ) + ( val2[x] - val2[x+2] );
float totDelta = (val0[x] - val0[x + 2]) + (val1[x] - val1[x + 2]) + (val2[x] - val2[x + 2]);
float deltaZX = totDelta * amplitude / 6.f;
totDelta = ( val0[x] - val2[x] ) + ( val0[x+1] - val2[x+1] ) + ( val0[x+2] - val2[x+2] );
totDelta = (val0[x] - val2[x]) + (val0[x + 1] - val2[x + 1]) + (val0[x + 2] - val2[x + 2]);
float deltaZY = totDelta * amplitude / 6.f;
XMVECTOR vx = XMVectorSetZ( g_XMNegIdentityR0, deltaZX ); // (-1.0f, 0.0f, deltaZX)
XMVECTOR vy = XMVectorSetZ( g_XMNegIdentityR1, deltaZY ); // (0.0f, -1.0f, deltaZY)
XMVECTOR vx = XMVectorSetZ(g_XMNegIdentityR0, deltaZX); // (-1.0f, 0.0f, deltaZX)
XMVECTOR vy = XMVectorSetZ(g_XMNegIdentityR1, deltaZY); // (0.0f, -1.0f, deltaZY)
XMVECTOR normal = XMVector3Normalize( XMVector3Cross( vx, vy ) );
XMVECTOR normal = XMVector3Normalize(XMVector3Cross(vx, vy));
// Compute alpha (1.0 or an occlusion term)
float alpha = 1.f;
if ( flags & CNMAP_COMPUTE_OCCLUSION )
if (flags & CNMAP_COMPUTE_OCCLUSION)
{
float delta = 0.f;
float c = val1[x+1];
float c = val1[x + 1];
float t = val0[x] - c; if ( t > 0.f ) delta += t;
t = val0[x+1] - c; if ( t > 0.f ) delta += t;
t = val0[x+2] - c; if ( t > 0.f ) delta += t;
t = val1[x] - c; if ( t > 0.f ) delta += t;
float t = val0[x] - c; if (t > 0.f) delta += t;
t = val0[x + 1] - c; if (t > 0.f) delta += t;
t = val0[x + 2] - c; if (t > 0.f) delta += t;
t = val1[x] - c; if (t > 0.f) delta += t;
// Skip current pixel
t = val1[x+2] - c; if ( t > 0.f ) delta += t;
t = val2[x] - c; if ( t > 0.f ) delta += t;
t = val2[x+1] - c; if ( t > 0.f ) delta += t;
t = val2[x+2] - c; if ( t > 0.f ) delta += t;
t = val1[x + 2] - c; if (t > 0.f) delta += t;
t = val2[x] - c; if (t > 0.f) delta += t;
t = val2[x + 1] - c; if (t > 0.f) delta += t;
t = val2[x + 2] - c; if (t > 0.f) delta += t;
// Average delta (divide by 8, scale by amplitude factor)
delta *= 0.125f * amplitude;
if ( delta > 0.f )
if (delta > 0.f)
{
// If < 0, then no occlusion
float r = sqrtf( 1.f + delta*delta );
float r = sqrtf(1.f + delta*delta);
alpha = (r - delta) / r;
}
}
// Encode based on target format
if ( convFlags & CONVF_UNORM )
if (convFlags & CONVF_UNORM)
{
// 0.5f*normal + 0.5f -or- invert sign case: -0.5f*normal + 0.5f
XMVECTOR n1 = XMVectorMultiplyAdd( (flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf );
*dptr++ = XMVectorSetW( n1, alpha );
XMVECTOR n1 = XMVectorMultiplyAdd((flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf);
*dptr++ = XMVectorSetW(n1, alpha);
}
else if ( flags & CNMAP_INVERT_SIGN )
else if (flags & CNMAP_INVERT_SIGN)
{
*dptr++ = XMVectorSetW( XMVectorNegate( normal ), alpha );
*dptr++ = XMVectorSetW(XMVectorNegate(normal), alpha);
}
else
{
*dptr++ = XMVectorSetW( normal, alpha );
*dptr++ = XMVectorSetW(normal, alpha);
}
}
if ( !_StoreScanline( pDest, normalMap.rowPitch, format, target, width ) )
if (!_StoreScanline(pDest, normalMap.rowPitch, format, target, width))
return E_FAIL;
// Cycle buffers
@ -241,6 +246,7 @@ static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_
}
return S_OK;
}
}
@ -252,14 +258,18 @@ static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_
// Generates a normal map from a height-map
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
DXGI_FORMAT format, ScratchImage& normalMap )
HRESULT DirectX::ComputeNormalMap(
const Image& srcImage,
DWORD flags,
float amplitude,
DXGI_FORMAT format,
ScratchImage& normalMap)
{
if ( !srcImage.pixels || !IsValid(format) )
if (!srcImage.pixels || !IsValid(format))
return E_INVALIDARG;
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
switch( flags & 0xf )
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
switch (flags & 0xf)
{
case 0:
case CNMAP_CHANNEL_RED:
@ -273,28 +283,28 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
return E_INVALIDARG;
}
if ( IsCompressed(format) || IsCompressed(srcImage.format)
if (IsCompressed(format) || IsCompressed(srcImage.format)
|| IsTypeless(format) || IsTypeless(srcImage.format)
|| IsPlanar(format) || IsPlanar(srcImage.format)
|| IsPalettized(format) || IsPalettized(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|| IsPalettized(format) || IsPalettized(srcImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Setup target image
normalMap.Release();
HRESULT hr = normalMap.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = normalMap.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = normalMap.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = normalMap.GetImage(0, 0, 0);
if (!img)
{
normalMap.Release();
return E_POINTER;
}
hr = _ComputeNMap( srcImage, flags, amplitude, format, *img );
if ( FAILED(hr) )
hr = ComputeNMap(srcImage, flags, amplitude, format, *img);
if (FAILED(hr))
{
normalMap.Release();
return hr;
@ -304,20 +314,26 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
}
_Use_decl_annotations_
HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD flags, float amplitude, DXGI_FORMAT format, ScratchImage& normalMaps )
HRESULT DirectX::ComputeNormalMap(
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DWORD flags,
float amplitude,
DXGI_FORMAT format,
ScratchImage& normalMaps)
{
if ( !srcImages || !nimages || !IsValid(format) )
if (!srcImages || !nimages || !IsValid(format))
return E_INVALIDARG;
if ( IsCompressed(format) || IsCompressed(metadata.format)
if (IsCompressed(format) || IsCompressed(metadata.format)
|| IsTypeless(format) || IsTypeless(metadata.format)
|| IsPlanar(format) || IsPlanar(metadata.format)
|| IsPalettized(format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|| IsPalettized(format) || IsPalettized(metadata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
switch( flags & 0xf )
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
switch (flags & 0xf)
{
case 0:
case CNMAP_CHANNEL_RED:
@ -335,42 +351,42 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
TexMetadata mdata2 = metadata;
mdata2.format = format;
HRESULT hr = normalMaps.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = normalMaps.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != normalMaps.GetImageCount() )
if (nimages != normalMaps.GetImageCount())
{
normalMaps.Release();
return E_FAIL;
}
const Image* dest = normalMaps.GetImages();
if ( !dest )
if (!dest)
{
normalMaps.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
assert( dest[ index ].format == format );
assert(dest[index].format == format);
const Image& src = srcImages[ index ];
if ( IsCompressed( src.format ) || IsTypeless( src.format ) )
const Image& src = srcImages[index];
if (IsCompressed(src.format) || IsTypeless(src.format))
{
normalMaps.Release();
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
if (src.width != dest[index].width || src.height != dest[index].height)
{
normalMaps.Release();
return E_FAIL;
}
hr = _ComputeNMap( src, flags, amplitude, format, dest[ index ] );
if ( FAILED(hr) )
hr = ComputeNMap(src, flags, amplitude, format, dest[index]);
if (FAILED(hr))
{
normalMaps.Release();
return hr;
@ -379,5 +395,3 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
return S_OK;
}
}; // namespace

View File

@ -175,40 +175,40 @@ namespace DirectX
void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
LPVOID pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
void* pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT format, _In_ DWORD flags );
void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_)
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
LPVOID pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
void* pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT format, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize,
bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) void* pDestination, _In_ size_t outSize,
_In_ DXGI_FORMAT outFormat,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
_In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
_Success_(return != false)
bool __cdecl _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
_In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _StoreScanline( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
bool __cdecl _StoreScanline( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0 );
_Success_(return != false)
bool __cdecl _StoreScanlineLinear( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
bool __cdecl _StoreScanlineLinear( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags, _In_ float threshold = 0 );
_Success_(return != false)
bool __cdecl _StoreScanlineDither( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
bool __cdecl _StoreScanlineDither( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ float threshold, size_t y, size_t z,
_Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors );
@ -225,6 +225,6 @@ namespace DirectX
//---------------------------------------------------------------------------------
// DDS helper functions
HRESULT __cdecl _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
_Out_writes_bytes_to_opt_(maxsize, required) LPVOID pDestination, _In_ size_t maxsize, _Out_ size_t& required );
_Out_writes_bytes_to_opt_(maxsize, required) void* pDestination, _In_ size_t maxsize, _Out_ size_t& required );
}; // namespace

View File

@ -15,38 +15,40 @@
#include "directxtexp.h"
namespace DirectX
using namespace DirectX;
namespace
{
static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& destImage )
{
assert( srcImage.width == destImage.width );
assert( srcImage.height == destImage.height );
HRESULT PremultiplyAlpha_(const Image& srcImage, const Image& destImage)
{
assert(srcImage.width == destImage.width);
assert(srcImage.height == destImage.height);
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
if (!scanline)
return E_OUTOFMEMORY;
const uint8_t *pSrc = srcImage.pixels;
uint8_t *pDest = destImage.pixels;
if ( !pSrc || !pDest )
if (!pSrc || !pDest)
return E_POINTER;
for( size_t h = 0; h < srcImage.height; ++h )
for (size_t h = 0; h < srcImage.height; ++h)
{
if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
return E_FAIL;
XMVECTOR* ptr = scanline.get();
for( size_t w = 0; w < srcImage.width; ++w )
for (size_t w = 0; w < srcImage.width; ++w)
{
XMVECTOR v = *ptr;
XMVECTOR alpha = XMVectorSplatW( *ptr );
alpha = XMVectorMultiply( v, alpha );
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
XMVECTOR alpha = XMVectorSplatW(*ptr);
alpha = XMVectorMultiply(v, alpha);
*(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110);
}
if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width))
return E_FAIL;
pSrc += srcImage.rowPitch;
@ -54,42 +56,42 @@ static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image&
}
return S_OK;
}
}
static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
{
assert( srcImage.width == destImage.width );
assert( srcImage.height == destImage.height );
HRESULT PremultiplyAlphaLinear(const Image& srcImage, DWORD flags, const Image& destImage)
{
assert(srcImage.width == destImage.width);
assert(srcImage.height == destImage.height);
static_assert( TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
static_assert(TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
flags &= TEX_PMALPHA_SRGB;
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
if (!scanline)
return E_OUTOFMEMORY;
const uint8_t *pSrc = srcImage.pixels;
uint8_t *pDest = destImage.pixels;
if ( !pSrc || !pDest )
if (!pSrc || !pDest)
return E_POINTER;
for( size_t h = 0; h < srcImage.height; ++h )
for (size_t h = 0; h < srcImage.height; ++h)
{
if ( !_LoadScanlineLinear( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags ) )
if (!_LoadScanlineLinear(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags))
return E_FAIL;
XMVECTOR* ptr = scanline.get();
for( size_t w = 0; w < srcImage.width; ++w )
for (size_t w = 0; w < srcImage.width; ++w)
{
XMVECTOR v = *ptr;
XMVECTOR alpha = XMVectorSplatW( *ptr );
alpha = XMVectorMultiply( v, alpha );
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
XMVECTOR alpha = XMVectorSplatW(*ptr);
alpha = XMVectorMultiply(v, alpha);
*(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110);
}
if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags ) )
if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags))
return E_FAIL;
pSrc += srcImage.rowPitch;
@ -97,6 +99,7 @@ static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD f
}
return S_OK;
}
}
@ -108,34 +111,37 @@ static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD f
// Converts to a premultiplied alpha version of the texture
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image )
HRESULT DirectX::PremultiplyAlpha(
const Image& srcImage,
DWORD flags,
ScratchImage& image)
{
if ( !srcImage.pixels )
if (!srcImage.pixels)
return E_POINTER;
if ( IsCompressed(srcImage.format)
if (IsCompressed(srcImage.format)
|| IsPlanar(srcImage.format)
|| IsPalettized(srcImage.format)
|| IsTypeless(srcImage.format)
|| !HasAlpha(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|| !HasAlpha(srcImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( (srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX) )
if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX))
return E_INVALIDARG;
HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *rimage = image.GetImage( 0, 0, 0 );
if ( !rimage )
const Image *rimage = image.GetImage(0, 0, 0);
if (!rimage)
{
image.Release();
return E_POINTER;
}
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( srcImage, *rimage ) : _PremultiplyAlphaLinear( srcImage, flags, *rimage );
if ( FAILED(hr) )
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(srcImage, *rimage) : PremultiplyAlphaLinear(srcImage, flags, *rimage);
if (FAILED(hr))
{
image.Release();
return hr;
@ -149,22 +155,27 @@ HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& imag
// Converts to a premultiplied alpha version of the texture (complex)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result )
HRESULT DirectX::PremultiplyAlpha(
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DWORD flags,
ScratchImage& result)
{
if ( !srcImages || !nimages )
if (!srcImages || !nimages)
return E_INVALIDARG;
if ( IsCompressed(metadata.format)
if (IsCompressed(metadata.format)
|| IsPlanar(metadata.format)
|| IsPalettized(metadata.format)
|| IsTypeless(metadata.format)
|| !HasAlpha(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|| !HasAlpha(metadata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( (metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX) )
if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX))
return E_INVALIDARG;
if ( metadata.IsPMAlpha() )
if (metadata.IsPMAlpha())
{
// Already premultiplied
return E_FAIL;
@ -172,46 +183,46 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
TexMetadata mdata2 = metadata;
mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED);
HRESULT hr = result.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = result.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != result.GetImageCount() )
if (nimages != result.GetImageCount())
{
result.Release();
return E_FAIL;
}
const Image* dest = result.GetImages();
if ( !dest )
if (!dest)
{
result.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
const Image& src = srcImages[ index ];
if ( src.format != metadata.format )
const Image& src = srcImages[index];
if (src.format != metadata.format)
{
result.Release();
return E_FAIL;
}
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
return E_FAIL;
const Image& dst = dest[ index ];
assert( dst.format == metadata.format );
const Image& dst = dest[index];
assert(dst.format == metadata.format);
if ( src.width != dst.width || src.height != dst.height )
if (src.width != dst.width || src.height != dst.height)
{
result.Release();
return E_FAIL;
}
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( src, dst ) : _PremultiplyAlphaLinear( src, flags, dst );
if ( FAILED(hr) )
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(src, dst) : PremultiplyAlphaLinear(src, flags, dst);
if (FAILED(hr))
{
result.Release();
return hr;
@ -220,5 +231,3 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
return S_OK;
}
}; // namespace

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,6 @@
#include "directxtexp.h"
using Microsoft::WRL::ComPtr;
#if defined(_XBOX_ONE) && defined(_TITLE)
static_assert(XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT == DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT, "Xbox One XDK mismatch detected");
static_assert(XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT == DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT, "Xbox One XDK mismatch detected");
@ -33,19 +31,23 @@ static_assert(WIN10_DXGI_FORMAT_V208 == DXGI_FORMAT_V208, "Windows SDK mismatch
static_assert(WIN10_DXGI_FORMAT_V408 == DXGI_FORMAT_V408, "Windows SDK mismatch detected");
#endif
using namespace DirectX;
using Microsoft::WRL::ComPtr;
//-------------------------------------------------------------------------------------
// WIC Pixel Format Translation Data
//-------------------------------------------------------------------------------------
struct WICTranslate
namespace
{
//-------------------------------------------------------------------------------------
// WIC Pixel Format Translation Data
//-------------------------------------------------------------------------------------
struct WICTranslate
{
GUID wic;
DXGI_FORMAT format;
bool srgb;
};
};
static const WICTranslate g_WICFormats[] =
{
const WICTranslate g_WICFormats[] =
{
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false },
@ -69,32 +71,30 @@ static const WICTranslate g_WICFormats[] =
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM, false },
{ GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false },
};
};
static bool g_WIC2 = false;
static IWICImagingFactory* g_Factory = nullptr;
bool g_WIC2 = false;
IWICImagingFactory* g_Factory = nullptr;
}
namespace DirectX
{
//=====================================================================================
// WIC Utilities
//=====================================================================================
_Use_decl_annotations_
DXGI_FORMAT _WICToDXGI( const GUID& guid )
DXGI_FORMAT DirectX::_WICToDXGI(const GUID& guid)
{
for( size_t i=0; i < _countof(g_WICFormats); ++i )
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
{
if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 )
if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
return g_WICFormats[i].format;
}
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( g_WIC2 )
if (g_WIC2)
{
if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 )
if (memcmp(&GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID)) == 0)
return DXGI_FORMAT_R32G32B32_FLOAT;
}
#endif
@ -103,7 +103,7 @@ DXGI_FORMAT _WICToDXGI( const GUID& guid )
}
_Use_decl_annotations_
bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
bool DirectX::_DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
{
switch( format )
{
@ -163,28 +163,28 @@ bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
return false;
}
DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID )
DWORD DirectX::_CheckWICColorSpace(_In_ const GUID& sourceGUID, _In_ const GUID& targetGUID)
{
DWORD srgb = 0;
for( size_t i=0; i < _countof(g_WICFormats); ++i )
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
{
if ( memcmp( &g_WICFormats[i].wic, &sourceGUID, sizeof(GUID) ) == 0 )
if (memcmp(&g_WICFormats[i].wic, &sourceGUID, sizeof(GUID)) == 0)
{
if ( g_WICFormats[i].srgb )
if (g_WICFormats[i].srgb)
srgb |= TEX_FILTER_SRGB_IN;
}
if ( memcmp( &g_WICFormats[i].wic, &targetGUID, sizeof(GUID) ) == 0 )
if (memcmp(&g_WICFormats[i].wic, &targetGUID, sizeof(GUID)) == 0)
{
if ( g_WICFormats[i].srgb )
if (g_WICFormats[i].srgb)
srgb |= TEX_FILTER_SRGB_OUT;
}
}
if ( (srgb & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
if ((srgb & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT))
{
srgb &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
srgb &= ~(TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT);
}
return srgb;
@ -195,9 +195,9 @@ DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetG
// Public helper function to get common WIC codec GUIDs
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
REFGUID GetWICCodec( WICCodecs codec )
REFGUID DirectX::GetWICCodec(WICCodecs codec)
{
switch( codec )
switch (codec)
{
case WIC_CODEC_BMP:
return GUID_ContainerFormatBmp;
@ -229,9 +229,9 @@ REFGUID GetWICCodec( WICCodecs codec )
//-------------------------------------------------------------------------------------
// Singleton function for WIC factory
//-------------------------------------------------------------------------------------
IWICImagingFactory* GetWICFactory( bool& iswic2 )
IWICImagingFactory* DirectX::GetWICFactory(bool& iswic2)
{
if ( g_Factory )
if (g_Factory)
{
iswic2 = g_WIC2;
return g_Factory;
@ -240,9 +240,9 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
InitOnceExecuteOnce(&s_initOnce,
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
[](PINIT_ONCE, PVOID, LPVOID *factory) -> BOOL
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
@ -270,17 +270,17 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
#else
g_WIC2 = false;
return SUCCEEDED( CoCreateInstance(
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
factory) ) ? TRUE : FALSE;
#endif
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory) );
factory)) ? TRUE : FALSE;
#endif
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory));
iswic2 = g_WIC2;
return g_Factory;
@ -290,7 +290,7 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
//-------------------------------------------------------------------------------------
// Optional initializer for WIC factory
//-------------------------------------------------------------------------------------
void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
void DirectX::SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
{
if (pWIC == g_Factory)
return;
@ -311,7 +311,7 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
g_WIC2 = iswic2;
std::swap(pWIC, g_Factory);
if ( pWIC )
if (pWIC)
pWIC->Release();
}
@ -323,9 +323,9 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsPacked(DXGI_FORMAT fmt)
bool DirectX::IsPacked(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
@ -342,9 +342,9 @@ bool IsPacked(DXGI_FORMAT fmt)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsVideo(DXGI_FORMAT fmt)
bool DirectX::IsVideo(DXGI_FORMAT fmt)
{
switch ( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_Y410:
@ -379,9 +379,9 @@ bool IsVideo(DXGI_FORMAT fmt)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsPlanar(DXGI_FORMAT fmt)
bool DirectX::IsPlanar(DXGI_FORMAT fmt)
{
switch ( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_NV12: // 4:2:0 8-bit
case DXGI_FORMAT_P010: // 4:2:0 10-bit
@ -403,15 +403,14 @@ bool IsPlanar(DXGI_FORMAT fmt)
default:
return false;
}
}
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsDepthStencil(DXGI_FORMAT fmt)
bool DirectX::IsDepthStencil(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
@ -434,9 +433,9 @@ bool IsDepthStencil(DXGI_FORMAT fmt)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
bool DirectX::IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32_TYPELESS:
@ -478,9 +477,9 @@ bool IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool HasAlpha(DXGI_FORMAT fmt)
bool DirectX::HasAlpha(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -541,9 +540,9 @@ bool HasAlpha(DXGI_FORMAT fmt)
// Returns bits-per-pixel for a given DXGI format, or 0 on failure
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
size_t BitsPerPixel( DXGI_FORMAT fmt )
size_t DirectX::BitsPerPixel(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -703,9 +702,9 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
// For mixed formats, it returns the largest color-depth in the format
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
size_t BitsPerColor( DXGI_FORMAT fmt )
size_t DirectX::BitsPerColor(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -869,10 +868,10 @@ size_t BitsPerColor( DXGI_FORMAT fmt )
// based on DXGI format, width, and height
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
size_t& rowPitch, size_t& slicePitch, DWORD flags )
void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
size_t& rowPitch, size_t& slicePitch, DWORD flags)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
@ -882,8 +881,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
case DXGI_FORMAT_BC4_SNORM:
assert(IsCompressed(fmt));
{
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
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;
@ -907,8 +906,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
case DXGI_FORMAT_BC7_UNORM_SRGB:
assert(IsCompressed(fmt));
{
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
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;
@ -919,22 +918,22 @@ void 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;
rowPitch = ((width + 1) >> 1) * 4;
slicePitch = rowPitch * height;
break;
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y216:
assert(IsPacked(fmt));
rowPitch = ( ( width + 1 ) >> 1 ) * 8;
rowPitch = ((width + 1) >> 1) * 8;
slicePitch = rowPitch * 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 ) );
rowPitch = ((width + 1) >> 1) * 2;
slicePitch = rowPitch * (height + ((height + 1) >> 1));
break;
case DXGI_FORMAT_P010:
@ -943,84 +942,84 @@ void 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 ) );
rowPitch = ((width + 1) >> 1) * 4;
slicePitch = rowPitch * (height + ((height + 1) >> 1));
break;
case DXGI_FORMAT_NV11:
assert(IsPlanar(fmt));
rowPitch = ( ( width + 3 ) >> 2 ) * 4;
rowPitch = ((width + 3) >> 2) * 4;
slicePitch = rowPitch * height * 2;
break;
case WIN10_DXGI_FORMAT_P208:
assert(IsPlanar(fmt));
rowPitch = ( ( width + 1 ) >> 1 ) * 2;
rowPitch = ((width + 1) >> 1) * 2;
slicePitch = rowPitch * height * 2;
break;
case WIN10_DXGI_FORMAT_V208:
assert(IsPlanar(fmt));
rowPitch = width;
slicePitch = rowPitch * ( height + ( ( ( height + 1 ) >> 1 ) * 2 ) );
slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2));
break;
case WIN10_DXGI_FORMAT_V408:
assert(IsPlanar(fmt));
rowPitch = width;
slicePitch = rowPitch * ( height + ( ( height >> 1 ) * 4 ) );
slicePitch = rowPitch * (height + ((height >> 1) * 4));
break;
default:
assert( IsValid(fmt) );
assert( !IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt) );
assert(IsValid(fmt));
assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt));
{
size_t bpp;
if ( flags & CP_FLAGS_24BPP )
if (flags & CP_FLAGS_24BPP)
bpp = 24;
else if ( flags & CP_FLAGS_16BPP )
else if (flags & CP_FLAGS_16BPP)
bpp = 16;
else if ( flags & CP_FLAGS_8BPP )
else if (flags & CP_FLAGS_8BPP)
bpp = 8;
else
bpp = BitsPerPixel( fmt );
bpp = BitsPerPixel(fmt);
if ( flags & ( CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K ) )
if (flags & (CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K))
{
if ( flags & CP_FLAGS_PAGE4K )
if (flags & CP_FLAGS_PAGE4K)
{
rowPitch = ( ( width * bpp + 32767 ) / 32768 ) * 4096;
rowPitch = ((width * bpp + 32767) / 32768) * 4096;
slicePitch = rowPitch * height;
}
else if ( flags & CP_FLAGS_ZMM )
else if (flags & CP_FLAGS_ZMM)
{
rowPitch = ( ( width * bpp + 511 ) / 512 ) * 64;
rowPitch = ((width * bpp + 511) / 512) * 64;
slicePitch = rowPitch * height;
}
else if ( flags & CP_FLAGS_YMM )
else if (flags & CP_FLAGS_YMM)
{
rowPitch = ( ( width * bpp + 255 ) / 256) * 32;
rowPitch = ((width * bpp + 255) / 256) * 32;
slicePitch = rowPitch * height;
}
else if ( flags & CP_FLAGS_PARAGRAPH )
else if (flags & CP_FLAGS_PARAGRAPH)
{
rowPitch = ( ( width * bpp + 127 ) / 128 ) * 16;
rowPitch = ((width * bpp + 127) / 128) * 16;
slicePitch = rowPitch * 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);
rowPitch = ((width * bpp + 31) / 32) * sizeof(uint32_t);
slicePitch = rowPitch * height;
}
}
else
{
// Default byte alignment
rowPitch = ( width * bpp + 7 ) / 8;
rowPitch = (width * bpp + 7) / 8;
slicePitch = rowPitch * height;
}
}
@ -1031,9 +1030,9 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
size_t DirectX::ComputeScanlines(DXGI_FORMAT fmt, size_t height)
{
switch ( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
@ -1057,7 +1056,7 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB:
assert(IsCompressed(fmt));
return std::max<size_t>( 1, (height + 3) / 4 );
return std::max<size_t>(1, (height + 3) / 4);
case DXGI_FORMAT_NV11:
case WIN10_DXGI_FORMAT_P208:
@ -1066,11 +1065,11 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
case WIN10_DXGI_FORMAT_V208:
assert(IsPlanar(fmt));
return height + ( ( (height + 1) >> 1 ) * 2 );
return height + (((height + 1) >> 1) * 2);
case WIN10_DXGI_FORMAT_V408:
assert(IsPlanar(fmt));
return height + ( (height >> 1) * 4 );
return height + ((height >> 1) * 4);
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
@ -1080,11 +1079,11 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
assert(IsPlanar(fmt));
return height + ( ( height + 1 ) >> 1 );
return height + ((height + 1) >> 1);
default:
assert( IsValid(fmt) );
assert( !IsCompressed(fmt) && !IsPlanar(fmt) );
assert(IsValid(fmt));
assert(!IsCompressed(fmt) && !IsPlanar(fmt));
return height;
}
}
@ -1094,9 +1093,9 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
// Converts to an SRGB equivalent type if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeSRGB(DXGI_FORMAT fmt)
{
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R8G8B8A8_UNORM:
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
@ -1129,9 +1128,9 @@ DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
// Converts to a format to an equivalent TYPELESS format if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeTypeless(DXGI_FORMAT fmt)
{
switch( static_cast<int>( fmt ) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_UINT:
@ -1249,9 +1248,9 @@ DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
// Converts to a TYPELESS format to an equivalent UNORM format if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeTypelessUNORM(DXGI_FORMAT fmt)
{
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
return DXGI_FORMAT_R16G16B16A16_UNORM;
@ -1308,9 +1307,9 @@ DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
// Converts to a TYPELESS format to an equivalent FLOAT format if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeTypelessFLOAT(DXGI_FORMAT fmt)
{
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
@ -1344,25 +1343,25 @@ DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
//=====================================================================================
_Use_decl_annotations_
size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
size_t TexMetadata::ComputeIndex(size_t mip, size_t item, size_t slice) const
{
if ( mip >= mipLevels )
if (mip >= mipLevels)
return size_t(-1);
switch( dimension )
switch (dimension)
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
if ( slice > 0 )
if (slice > 0)
return size_t(-1);
if ( item >= arraySize )
if (item >= arraySize)
return size_t(-1);
return (item*( mipLevels ) + mip);
return (item*(mipLevels)+mip);
case TEX_DIMENSION_TEXTURE3D:
if ( item > 0 )
if (item > 0)
{
// No support for arrays of volumes
return size_t(-1);
@ -1372,14 +1371,14 @@ size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
size_t index = 0;
size_t d = depth;
for( size_t level = 0; level < mip; ++level )
for (size_t level = 0; level < mip; ++level)
{
index += d;
if ( d > 1 )
if (d > 1)
d >>= 1;
}
if ( slice >= d )
if (slice >= d)
return size_t(-1);
index += slice;
@ -1400,48 +1399,46 @@ size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
Blob& Blob::operator= (Blob&& moveFrom)
{
if ( this != &moveFrom )
if (this != &moveFrom)
{
Release();
_buffer = moveFrom._buffer;
_size = moveFrom._size;
m_buffer = moveFrom.m_buffer;
m_size = moveFrom.m_size;
moveFrom._buffer = nullptr;
moveFrom._size = 0;
moveFrom.m_buffer = nullptr;
moveFrom.m_size = 0;
}
return *this;
}
void Blob::Release()
{
if ( _buffer )
if (m_buffer)
{
_aligned_free( _buffer );
_buffer = nullptr;
_aligned_free(m_buffer);
m_buffer = nullptr;
}
_size = 0;
m_size = 0;
}
_Use_decl_annotations_
HRESULT Blob::Initialize( size_t size )
HRESULT Blob::Initialize(size_t size)
{
if ( !size )
if (!size)
return E_INVALIDARG;
Release();
_buffer = _aligned_malloc( size, 16 );
if ( !_buffer )
m_buffer = _aligned_malloc(size, 16);
if (!m_buffer)
{
Release();
return E_OUTOFMEMORY;
}
_size = size;
m_size = size;
return S_OK;
}
}; // namespace

File diff suppressed because it is too large Load Diff

View File

@ -63,36 +63,36 @@ struct LinearFilter
float weight1;
};
inline void _CreateLinearFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf )
inline void _CreateLinearFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf)
{
assert( source > 0 );
assert( dest > 0 );
assert( lf != 0 );
assert(source > 0);
assert(dest > 0);
assert(lf != 0);
float scale = float(source) / float(dest);
// Mirror is the same case as clamp for linear
for( size_t u = 0; u < dest; ++u )
for (size_t u = 0; u < dest; ++u)
{
float srcB = ( float(u) + 0.5f ) * scale + 0.5f;
float srcB = (float(u) + 0.5f) * scale + 0.5f;
ptrdiff_t isrcB = ptrdiff_t(srcB);
ptrdiff_t isrcA = isrcB - 1;
if ( isrcA < 0 )
if (isrcA < 0)
{
isrcA = ( wrap ) ? ( source - 1) : 0;
isrcA = (wrap) ? (source - 1) : 0;
}
if ( size_t(isrcB) >= source )
if (size_t(isrcB) >= source)
{
isrcB = ( wrap ) ? 0 : ( source - 1);
isrcB = (wrap) ? 0 : (source - 1);
}
float weight = 1.0f + float(isrcB) - srcB;
auto& entry = lf[ u ];
auto& entry = lf[u];
entry.u0 = size_t(isrcA);
entry.weight0 = weight;
@ -120,34 +120,34 @@ XMGLOBALCONST XMVECTORF32 g_cubicThird = { 1.f/3.f, 1.f/3.f, 1.f/3.f, 1.f/3.f };
XMGLOBALCONST XMVECTORF32 g_cubicSixth = { 1.f/6.f, 1.f/6.f, 1.f/6.f, 1.f/6.f };
XMGLOBALCONST XMVECTORF32 g_cubicHalf = { 1.f/2.f, 1.f/2.f, 1.f/2.f, 1.f/2.f };
inline ptrdiff_t bounduvw( ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror )
inline ptrdiff_t bounduvw(ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror)
{
if ( wrap )
if (wrap)
{
if ( u < 0 )
if (u < 0)
{
u = maxu + u + 1;
}
else if ( u > maxu )
else if (u > maxu)
{
u = u - maxu - 1;
}
}
else if ( mirror )
else if (mirror)
{
if ( u < 0 )
if (u < 0)
{
u = ( -u ) - 1;
u = (-u) - 1;
}
else if ( u > maxu )
else if (u > maxu)
{
u = maxu - (u - maxu - 1);
}
}
// Handles clamp, but also a safety factor for degenerate images for wrap/mirror
u = std::min<ptrdiff_t>( u, maxu );
u = std::max<ptrdiff_t>( u, 0 );
u = std::min<ptrdiff_t>(u, maxu);
u = std::max<ptrdiff_t>(u, 0);
return u;
}
@ -161,24 +161,24 @@ struct CubicFilter
float x;
};
inline void _CreateCubicFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf )
inline void _CreateCubicFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf)
{
assert( source > 0 );
assert( dest > 0 );
assert( cf != 0 );
assert(source > 0);
assert(dest > 0);
assert(cf != 0);
float scale = float(source) / float(dest);
for( size_t u = 0; u < dest; ++u )
for (size_t u = 0; u < dest; ++u)
{
float srcB = ( float(u) + 0.5f ) * scale - 0.5f;
float srcB = (float(u) + 0.5f) * scale - 0.5f;
ptrdiff_t isrcB = bounduvw( ptrdiff_t(srcB), source - 1, wrap, mirror );
ptrdiff_t isrcA = bounduvw( isrcB - 1, source - 1, wrap, mirror );
ptrdiff_t isrcC = bounduvw( isrcB + 1, source - 1, wrap, mirror );
ptrdiff_t isrcD = bounduvw( isrcB + 2, source - 1, wrap, mirror );
ptrdiff_t isrcB = bounduvw(ptrdiff_t(srcB), source - 1, wrap, mirror);
ptrdiff_t isrcA = bounduvw(isrcB - 1, source - 1, wrap, mirror);
ptrdiff_t isrcC = bounduvw(isrcB + 1, source - 1, wrap, mirror);
ptrdiff_t isrcD = bounduvw(isrcB + 2, source - 1, wrap, mirror);
auto& entry = cf[ u ];
auto& entry = cf[u];
entry.u0 = size_t(isrcA);
entry.u1 = size_t(isrcB);
entry.u2 = size_t(isrcC);
@ -246,10 +246,10 @@ namespace TriangleFilter
static const float TF_EPSILON = 0.00001f;
inline HRESULT _Create( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf )
inline HRESULT _Create(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf)
{
assert( source > 0 );
assert( dest > 0 );
assert(source > 0);
assert(dest > 0);
float scale = float(dest) / float(source);
float scaleInv = 0.5f / scale;
@ -258,109 +258,109 @@ namespace TriangleFilter
size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE;
float repeat = (wrap) ? 1.f : 0.f;
for( size_t u = 0; u < source; ++u )
for (size_t u = 0; u < source; ++u)
{
float src = float(u) - 0.5f;
float destMin = src * scale;
float destMax = destMin + scale;
totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t( destMax - destMin + repeat + 1.f ) * TF_TO_SIZE * 2;
totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t(destMax - destMin + repeat + 1.f) * TF_TO_SIZE * 2;
}
uint8_t* pFilter = nullptr;
if ( tf )
if (tf)
{
// See if existing filter memory block is large enough to reuse
if ( tf->totalSize >= totalSize )
if (tf->totalSize >= totalSize)
{
pFilter = reinterpret_cast<uint8_t*>( tf.get() );
pFilter = reinterpret_cast<uint8_t*>(tf.get());
}
else
{
// Need to reallocate filter memory block
tf.reset( nullptr );
tf.reset(nullptr);
}
}
if ( !tf )
if (!tf)
{
// Allocate filter memory block
pFilter = new (std::nothrow) uint8_t[ totalSize ];
if ( !pFilter )
pFilter = new (std::nothrow) uint8_t[totalSize];
if (!pFilter)
return E_OUTOFMEMORY;
tf.reset( reinterpret_cast<Filter*>( pFilter ) );
tf.reset(reinterpret_cast<Filter*>(pFilter));
tf->totalSize = totalSize;
}
assert( pFilter != 0 );
assert(pFilter != 0);
// Filter setup
size_t sizeInBytes = TF_FILTER_SIZE;
size_t accumU = 0;
float accumWeight = 0.f;
for( size_t u = 0; u < source; ++u )
for (size_t u = 0; u < source; ++u)
{
// Setup from entry
size_t sizeFrom = sizeInBytes;
auto pFrom = reinterpret_cast<FilterFrom*>( pFilter + sizeInBytes );
auto pFrom = reinterpret_cast<FilterFrom*>(pFilter + sizeInBytes);
sizeInBytes += TF_FROM_SIZE;
if ( sizeInBytes > totalSize )
if (sizeInBytes > totalSize)
return E_FAIL;
size_t toCount = 0;
// Perform two passes to capture the influences from both sides
for( size_t j = 0; j < 2; ++j )
for (size_t j = 0; j < 2; ++j)
{
float src = float( u + j ) - 0.5f;
float src = float(u + j) - 0.5f;
float destMin = src * scale;
float destMax = destMin + scale;
if ( !wrap )
if (!wrap)
{
// Clamp
if ( destMin < 0.f )
if (destMin < 0.f)
destMin = 0.f;
if ( destMax > float(dest) )
if (destMax > float(dest))
destMax = float(dest);
}
for( auto k = static_cast<ptrdiff_t>( floorf( destMin ) ); float(k) < destMax; ++k )
for (auto k = static_cast<ptrdiff_t>(floorf(destMin)); float(k) < destMax; ++k)
{
float d0 = float(k);
float d1 = d0 + 1.f;
size_t u0;
if ( k < 0 )
if (k < 0)
{
// Handle wrap
u0 = size_t( k + ptrdiff_t(dest) );
u0 = size_t(k + ptrdiff_t(dest));
}
else if ( k >= ptrdiff_t(dest) )
else if (k >= ptrdiff_t(dest))
{
// Handle wrap
u0 = size_t( k - ptrdiff_t(dest) );
u0 = size_t(k - ptrdiff_t(dest));
}
else
{
u0 = size_t( k );
u0 = size_t(k);
}
// Save previous accumulated weight (if any)
if ( u0 != accumU )
if (u0 != accumU)
{
if ( accumWeight > TF_EPSILON )
if (accumWeight > TF_EPSILON)
{
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
auto pTo = reinterpret_cast<FilterTo*>(pFilter + sizeInBytes);
sizeInBytes += TF_TO_SIZE;
++toCount;
if ( sizeInBytes > totalSize )
if (sizeInBytes > totalSize)
return E_FAIL;
pTo->u = accumU;
@ -372,33 +372,33 @@ namespace TriangleFilter
}
// Clip destination
if ( d0 < destMin )
if (d0 < destMin)
d0 = destMin;
if ( d1 > destMax )
if (d1 > destMax)
d1 = destMax;
// Calculate average weight over destination pixel
float weight;
if ( !wrap && src < 0.f )
if (!wrap && src < 0.f)
weight = 1.f;
else if ( !wrap && ( ( src + 1.f ) >= float(source) ) )
else if (!wrap && ((src + 1.f) >= float(source)))
weight = 0.f;
else
weight = (d0 + d1) * scaleInv - src;
accumWeight += (d1 - d0) * ( j ? (1.f - weight) : weight );
accumWeight += (d1 - d0) * (j ? (1.f - weight) : weight);
}
}
// Store accumulated weight
if ( accumWeight > TF_EPSILON )
if (accumWeight > TF_EPSILON)
{
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
auto pTo = reinterpret_cast<FilterTo*>(pFilter + sizeInBytes);
sizeInBytes += TF_TO_SIZE;
++toCount;
if ( sizeInBytes > totalSize )
if (sizeInBytes > totalSize)
return E_FAIL;
pTo->u = accumU;
@ -417,6 +417,6 @@ namespace TriangleFilter
return S_OK;
}
}; // namespace
}; // namespace TriangleFilter
}; // namespace
}; // namespace DirectX

View File

@ -229,7 +229,7 @@ namespace
class auto_delete_file_wic
{
public:
auto_delete_file_wic(ComPtr<IWICStream>& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {}
auto_delete_file_wic(ComPtr<IWICStream>& hFile, const wchar_t* szFile) : m_handle(hFile), m_filename(szFile) {}
~auto_delete_file_wic()
{
if (m_filename)
@ -242,7 +242,7 @@ namespace
void clear() { m_filename = 0; }
private:
LPCWSTR m_filename;
const wchar_t* m_filename;
ComPtr<IWICStream>& m_handle;
auto_delete_file_wic(const auto_delete_file_wic&) = delete;
@ -705,7 +705,7 @@ namespace
IWICImagingFactory* factory = nullptr;
InitOnceExecuteOnce(&s_initOnce,
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
[](PINIT_ONCE, PVOID, LPVOID *factory) -> BOOL
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
@ -751,7 +751,7 @@ namespace
//--------------------------------------------------------------------------------------
HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_z_ LPCWSTR fileName )
_In_z_ const wchar_t* fileName )
{
if ( !fileName )
return E_INVALIDARG;
@ -764,9 +764,9 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
// Create file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, 0 ) ) );
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE | DELETE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, nullptr ) ) );
#endif
if ( !hFile )
return HRESULT_FROM_WIN32( GetLastError() );
@ -912,7 +912,7 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR fileName,
_In_z_ const wchar_t* fileName,
_In_opt_ const GUID* targetFormat,
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps )
{

View File

@ -32,12 +32,12 @@ namespace DirectX
{
HRESULT SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_z_ LPCWSTR fileName );
_In_z_ const wchar_t* fileName );
HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR fileName,
_In_z_ const wchar_t* fileName,
_In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps = nullptr );
}

View File

@ -839,11 +839,7 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
return hr;
// Create file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0 ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
#endif
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, nullptr ) ) );
if ( !hFile )
return HRESULT_FROM_WIN32( GetLastError() );
@ -972,13 +968,13 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
// Write header & pixels
DWORD bytesWritten;
if ( !WriteFile( hFile.get(), fileHeader, static_cast<DWORD>( headerSize ), &bytesWritten, 0 ) )
if ( !WriteFile( hFile.get(), fileHeader, static_cast<DWORD>( headerSize ), &bytesWritten, nullptr ) )
return HRESULT_FROM_WIN32( GetLastError() );
if ( bytesWritten != headerSize )
return E_FAIL;
if ( !WriteFile( hFile.get(), pixels.get(), static_cast<DWORD>( slicePitch ), &bytesWritten, 0 ) )
if ( !WriteFile( hFile.get(), pixels.get(), static_cast<DWORD>( slicePitch ), &bytesWritten, nullptr ) )
return HRESULT_FROM_WIN32( GetLastError() );
if ( bytesWritten != slicePitch )

View File

@ -34,7 +34,8 @@
namespace DirectX
{
// Standard version
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromMemory(
_In_ ID3D11Device* d3dDevice,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture,
@ -42,7 +43,8 @@ namespace DirectX
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
@ -50,7 +52,8 @@ namespace DirectX
);
// Standard version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromMemory(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
@ -59,7 +62,8 @@ namespace DirectX
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture,
@ -68,11 +72,12 @@ namespace DirectX
);
// Extended version
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromMemoryEx(
_In_ ID3D11Device* d3dDevice,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
@ -81,7 +86,8 @@ namespace DirectX
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
@ -94,7 +100,8 @@ namespace DirectX
);
// Extended version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromMemoryEx(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
@ -108,7 +115,8 @@ namespace DirectX
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_In_ size_t maxsize,