mirror of
https://github.com/microsoft/DirectXTex
synced 2024-11-21 20:10:05 +00:00
General code cleanuP
This commit is contained in:
parent
53e66ba1e9
commit
51bc3d5b16
@ -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 )
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
@ -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, ¶m, sizeof( param ) );
|
||||
memcpy(mapped.pData, ¶m, 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, ¶m, sizeof( param ) );
|
||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
||||
memcpy(mapped.pData, ¶m, 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, ¶m, sizeof( param ) );
|
||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
||||
memcpy(mapped.pData, ¶m, 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, ¶m, sizeof( param ) );
|
||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
||||
memcpy(mapped.pData, ¶m, 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
|
@ -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 );
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
@ -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
|
@ -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 )
|
||||
{
|
||||
|
@ -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 );
|
||||
}
|
@ -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 )
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user