mirror of
https://github.com/microsoft/DirectXTex.git
synced 2025-07-15 14:30:13 +02:00
General code cleanuP
This commit is contained in:
parent
53e66ba1e9
commit
51bc3d5b16
@ -165,21 +165,11 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
// open the file
|
// open the file
|
||||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
|
||||||
ScopedHandle hFile( safe_handle( CreateFile2( fileName,
|
ScopedHandle hFile( safe_handle( CreateFile2( fileName,
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
FILE_SHARE_READ,
|
FILE_SHARE_READ,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
nullptr ) ) );
|
nullptr ) ) );
|
||||||
#else
|
|
||||||
ScopedHandle hFile( safe_handle( CreateFileW( fileName,
|
|
||||||
GENERIC_READ,
|
|
||||||
FILE_SHARE_READ,
|
|
||||||
nullptr,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
nullptr ) ) );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( !hFile )
|
if ( !hFile )
|
||||||
{
|
{
|
||||||
|
@ -21,32 +21,32 @@
|
|||||||
|
|
||||||
#include "BC.h"
|
#include "BC.h"
|
||||||
|
|
||||||
|
using namespace DirectX;
|
||||||
using namespace DirectX::PackedVector;
|
using namespace DirectX::PackedVector;
|
||||||
|
|
||||||
namespace DirectX
|
namespace
|
||||||
{
|
{
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
// Perceptual weightings for the importance of each channel.
|
||||||
// Constants
|
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);
|
// Decode/Encode RGB 5/6/5 colors
|
||||||
static const HDRColorA g_LuminanceInv(0.7154f / 0.2125f, 1.0f, 0.7154f / 0.0721f, 1.0f);
|
//-------------------------------------------------------------------------------------
|
||||||
|
inline void Decode565(_Out_ HDRColorA *pColor, _In_ const uint16_t w565)
|
||||||
//-------------------------------------------------------------------------------------
|
{
|
||||||
// Decode/Encode RGB 5/6/5 colors
|
pColor->r = (float)((w565 >> 11) & 31) * (1.0f / 31.0f);
|
||||||
//-------------------------------------------------------------------------------------
|
pColor->g = (float)((w565 >> 5) & 63) * (1.0f / 63.0f);
|
||||||
inline static void Decode565(_Out_ HDRColorA *pColor, _In_ const uint16_t w565)
|
pColor->b = (float)((w565 >> 0) & 31) * (1.0f / 31.0f);
|
||||||
{
|
|
||||||
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;
|
pColor->a = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static uint16_t Encode565(_In_ const HDRColorA *pColor)
|
inline uint16_t Encode565(_In_ const HDRColorA *pColor)
|
||||||
{
|
{
|
||||||
HDRColorA Color;
|
HDRColorA Color;
|
||||||
|
|
||||||
Color.r = (pColor->r < 0.0f) ? 0.0f : (pColor->r > 1.0f) ? 1.0f : pColor->r;
|
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;
|
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.g * 63.0f + 0.5f) << 5) |
|
||||||
(static_cast<int32_t>(Color.b * 31.0f + 0.5f) << 0));
|
(static_cast<int32_t>(Color.b * 31.0f + 0.5f) << 0));
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
|
void OptimizeRGB(
|
||||||
_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pPoints, _In_ size_t cSteps, _In_ DWORD flags)
|
_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 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 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 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 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 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 *pC = (3 == cSteps) ? pC3 : pC4;
|
||||||
const float *pD = (3 == cSteps) ? pD3 : pD4;
|
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 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);
|
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
|
#ifdef COLOR_WEIGHTS
|
||||||
if(pPoints[iPoint].a > 0.0f)
|
if (pPoints[iPoint].a > 0.0f)
|
||||||
#endif // COLOR_WEIGHTS
|
#endif // COLOR_WEIGHTS
|
||||||
{
|
{
|
||||||
if(pPoints[iPoint].r < X.r)
|
if (pPoints[iPoint].r < X.r)
|
||||||
X.r = pPoints[iPoint].r;
|
X.r = pPoints[iPoint].r;
|
||||||
|
|
||||||
if(pPoints[iPoint].g < X.g)
|
if (pPoints[iPoint].g < X.g)
|
||||||
X.g = pPoints[iPoint].g;
|
X.g = pPoints[iPoint].g;
|
||||||
|
|
||||||
if(pPoints[iPoint].b < X.b)
|
if (pPoints[iPoint].b < X.b)
|
||||||
X.b = pPoints[iPoint].b;
|
X.b = pPoints[iPoint].b;
|
||||||
|
|
||||||
if(pPoints[iPoint].r > Y.r)
|
if (pPoints[iPoint].r > Y.r)
|
||||||
Y.r = pPoints[iPoint].r;
|
Y.r = pPoints[iPoint].r;
|
||||||
|
|
||||||
if(pPoints[iPoint].g > Y.g)
|
if (pPoints[iPoint].g > Y.g)
|
||||||
Y.g = pPoints[iPoint].g;
|
Y.g = pPoints[iPoint].g;
|
||||||
|
|
||||||
if(pPoints[iPoint].b > Y.b)
|
if (pPoints[iPoint].b > Y.b)
|
||||||
Y.b = pPoints[iPoint].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;
|
float fAB = AB.r * AB.r + AB.g * AB.g + AB.b * AB.b;
|
||||||
|
|
||||||
// Single color block.. no need to root-find
|
// 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;
|
pX->r = X.r; pX->g = X.g; pX->b = X.b;
|
||||||
pY->r = Y.r; pY->g = Y.g; pY->b = Y.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;
|
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;
|
HDRColorA Pt;
|
||||||
Pt.r = (pPoints[iPoint].r - Mid.r) * Dir.r;
|
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];
|
float fDirMax = fDir[0];
|
||||||
size_t iDirMax = 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];
|
fDirMax = fDir[iDir];
|
||||||
iDirMax = iDir;
|
iDirMax = iDir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(iDirMax & 2)
|
if (iDirMax & 2)
|
||||||
{
|
{
|
||||||
float f = X.g; X.g = Y.g; Y.g = f;
|
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;
|
float f = X.b; X.b = Y.b; Y.b = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Two color block.. no need to root-find
|
// 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;
|
pX->r = X.r; pX->g = X.g; pX->b = X.b;
|
||||||
pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
|
pY->r = Y.r; pY->g = Y.g; pY->b = Y.b;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Use Newton's Method to find local minima of sum-of-squares error.
|
// 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
|
// Calculate new steps
|
||||||
HDRColorA pSteps[4];
|
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].r = X.r * pC[iStep] + Y.r * pD[iStep];
|
||||||
pSteps[iStep].g = X.g * pC[iStep] + Y.g * 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);
|
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;
|
break;
|
||||||
|
|
||||||
float fScale = fSteps / fLen;
|
float fScale = fSteps / fLen;
|
||||||
@ -246,7 +249,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
|
|||||||
HDRColorA dX, dY;
|
HDRColorA dX, dY;
|
||||||
d2X = d2Y = dX.r = dX.g = dX.b = dY.r = dY.g = dY.b = 0.0f;
|
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 +
|
float fDot = (pPoints[iPoint].r - X.r) * Dir.r +
|
||||||
(pPoints[iPoint].g - X.g) * Dir.g +
|
(pPoints[iPoint].g - X.g) * Dir.g +
|
||||||
@ -254,9 +257,9 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
|
|||||||
|
|
||||||
|
|
||||||
size_t iStep;
|
size_t iStep;
|
||||||
if(fDot <= 0.0f)
|
if (fDot <= 0.0f)
|
||||||
iStep = 0;
|
iStep = 0;
|
||||||
else if(fDot >= fSteps)
|
else if (fDot >= fSteps)
|
||||||
iStep = cSteps - 1;
|
iStep = cSteps - 1;
|
||||||
else
|
else
|
||||||
iStep = static_cast<size_t>(fDot + 0.5f);
|
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;
|
dY.b += fD * Diff.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Move endpoints
|
// Move endpoints
|
||||||
if(d2X > 0.0f)
|
if (d2X > 0.0f)
|
||||||
{
|
{
|
||||||
float f = -1.0f / d2X;
|
float f = -1.0f / d2X;
|
||||||
|
|
||||||
@ -297,7 +299,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
|
|||||||
X.b += dX.b * f;
|
X.b += dX.b * f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d2Y > 0.0f)
|
if (d2Y > 0.0f)
|
||||||
{
|
{
|
||||||
float f = -1.0f / d2Y;
|
float f = -1.0f / d2Y;
|
||||||
|
|
||||||
@ -306,7 +308,7 @@ static void OptimizeRGB(_Out_ HDRColorA *pX, _Out_ HDRColorA *pY,
|
|||||||
Y.b += dY.b * f;
|
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))
|
(dY.r * dY.r < fEpsilon) && (dY.g * dY.g < fEpsilon) && (dY.b * dY.b < fEpsilon))
|
||||||
{
|
{
|
||||||
break;
|
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;
|
pX->r = X.r; pX->g = X.g; pX->b = X.b;
|
||||||
pY->r = Y.r; pY->g = Y.g; pY->b = Y.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 )
|
inline void DecodeBC1(
|
||||||
{
|
_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor,
|
||||||
assert( pColor && pBC );
|
_In_ const D3DX_BC1 *pBC,
|
||||||
static_assert( sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes" );
|
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 clr0 = XMLoadU565(reinterpret_cast<const XMU565*>(&pBC->rgb[0]));
|
||||||
XMVECTOR clr1 = XMLoadU565( reinterpret_cast<const XMU565*>(&pBC->rgb[1]) );
|
XMVECTOR clr1 = XMLoadU565(reinterpret_cast<const XMU565*>(&pBC->rgb[1]));
|
||||||
|
|
||||||
clr0 = XMVectorMultiply( clr0, s_Scale );
|
clr0 = XMVectorMultiply(clr0, s_Scale);
|
||||||
clr1 = XMVectorMultiply( clr1, s_Scale );
|
clr1 = XMVectorMultiply(clr1, s_Scale);
|
||||||
|
|
||||||
clr0 = XMVectorSwizzle<2, 1, 0, 3>( clr0 );
|
clr0 = XMVectorSwizzle<2, 1, 0, 3>(clr0);
|
||||||
clr1 = XMVectorSwizzle<2, 1, 0, 3>( clr1 );
|
clr1 = XMVectorSwizzle<2, 1, 0, 3>(clr1);
|
||||||
|
|
||||||
clr0 = XMVectorSelect( g_XMIdentityR3, clr0, g_XMSelect1110 );
|
clr0 = XMVectorSelect(g_XMIdentityR3, clr0, g_XMSelect1110);
|
||||||
clr1 = XMVectorSelect( g_XMIdentityR3, clr1, g_XMSelect1110 );
|
clr1 = XMVectorSelect(g_XMIdentityR3, clr1, g_XMSelect1110);
|
||||||
|
|
||||||
XMVECTOR clr2, clr3;
|
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
|
clr3 = XMVectorZero(); // Alpha of 0
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clr2 = XMVectorLerp( clr0, clr1, 1.f/3.f );
|
clr2 = XMVectorLerp(clr0, clr1, 1.f / 3.f);
|
||||||
clr3 = XMVectorLerp( clr0, clr1, 2.f/3.f );
|
clr3 = XMVectorLerp(clr0, clr1, 2.f / 3.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t dw = pBC->bitmap;
|
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 0: pColor[i] = clr0; break;
|
||||||
case 1: pColor[i] = clr1; 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;
|
default: pColor[i] = clr3; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
|
void EncodeBC1(
|
||||||
static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor,
|
_Out_ D3DX_BC1 *pBC,
|
||||||
_In_ bool bColorKey, _In_ float alphaRef, _In_ DWORD flags)
|
_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *pColor,
|
||||||
{
|
bool bColorKey,
|
||||||
assert( pBC && pColor );
|
float alphaRef,
|
||||||
static_assert( sizeof(D3DX_BC1) == 8, "D3DX_BC1 should be 8 bytes" );
|
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
|
// Determine if we need to colorkey this block
|
||||||
size_t uSteps;
|
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;
|
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++;
|
uColorKey++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NUM_PIXELS_PER_BLOCK == uColorKey)
|
if (NUM_PIXELS_PER_BLOCK == uColorKey)
|
||||||
{
|
{
|
||||||
pBC->rgb[0] = 0x0000;
|
pBC->rgb[0] = 0x0000;
|
||||||
pBC->rgb[1] = 0xffff;
|
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));
|
memset(Error, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(HDRColorA));
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
for(i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||||
{
|
{
|
||||||
HDRColorA Clr;
|
HDRColorA Clr;
|
||||||
Clr.r = pColor[i].r;
|
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.g = Color[i].a * (Clr.g - Color[i].g);
|
||||||
Diff.b = Color[i].a * (Clr.b - Color[i].b);
|
Diff.b = Color[i].a * (Clr.b - Color[i].b);
|
||||||
|
|
||||||
if(3 != (i & 3))
|
if (3 != (i & 3))
|
||||||
{
|
{
|
||||||
assert( i < 15 );
|
assert(i < 15);
|
||||||
_Analysis_assume_( i < 15 );
|
_Analysis_assume_(i < 15);
|
||||||
Error[i + 1].r += Diff.r * (7.0f / 16.0f);
|
Error[i + 1].r += Diff.r * (7.0f / 16.0f);
|
||||||
Error[i + 1].g += Diff.g * (7.0f / 16.0f);
|
Error[i + 1].g += Diff.g * (7.0f / 16.0f);
|
||||||
Error[i + 1].b += Diff.b * (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].r += Diff.r * (3.0f / 16.0f);
|
||||||
Error[i + 3].g += Diff.g * (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].g += Diff.g * (5.0f / 16.0f);
|
||||||
Error[i + 4].b += Diff.b * (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 );
|
assert(i < 11);
|
||||||
_Analysis_assume_( i < 11 );
|
_Analysis_assume_(i < 11);
|
||||||
Error[i + 5].r += Diff.r * (1.0f / 16.0f);
|
Error[i + 5].r += Diff.r * (1.0f / 16.0f);
|
||||||
Error[i + 5].g += Diff.g * (1.0f / 16.0f);
|
Error[i + 5].g += Diff.g * (1.0f / 16.0f);
|
||||||
Error[i + 5].b += Diff.b * (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].r *= g_Luminance.r;
|
||||||
Color[i].g *= g_Luminance.g;
|
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);
|
OptimizeRGB(&ColorA, &ColorB, Color, uSteps, flags);
|
||||||
|
|
||||||
if ( flags & BC_FLAGS_UNIFORM )
|
if (flags & BC_FLAGS_UNIFORM)
|
||||||
{
|
{
|
||||||
ColorC = ColorA;
|
ColorC = ColorA;
|
||||||
ColorD = ColorB;
|
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 wColorA = Encode565(&ColorC);
|
||||||
uint16_t wColorB = Encode565(&ColorD);
|
uint16_t wColorB = Encode565(&ColorD);
|
||||||
|
|
||||||
if((uSteps == 4) && (wColorA == wColorB))
|
if ((uSteps == 4) && (wColorA == wColorB))
|
||||||
{
|
{
|
||||||
pBC->rgb[0] = wColorA;
|
pBC->rgb[0] = wColorA;
|
||||||
pBC->rgb[1] = wColorB;
|
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(&ColorC, wColorA);
|
||||||
Decode565(&ColorD, wColorB);
|
Decode565(&ColorD, wColorB);
|
||||||
|
|
||||||
if ( flags & BC_FLAGS_UNIFORM )
|
if (flags & BC_FLAGS_UNIFORM)
|
||||||
{
|
{
|
||||||
ColorA = ColorC;
|
ColorA = ColorC;
|
||||||
ColorB = ColorD;
|
ColorB = ColorD;
|
||||||
@ -540,7 +548,7 @@ static void EncodeBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) cons
|
|||||||
// Calculate color steps
|
// Calculate color steps
|
||||||
HDRColorA Step[4];
|
HDRColorA Step[4];
|
||||||
|
|
||||||
if((3 == uSteps) == (wColorA <= wColorB))
|
if ((3 == uSteps) == (wColorA <= wColorB))
|
||||||
{
|
{
|
||||||
pBC->rgb[0] = wColorA;
|
pBC->rgb[0] = wColorA;
|
||||||
pBC->rgb[1] = wColorB;
|
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 };
|
static const size_t pSteps4[] = { 0, 2, 3, 1 };
|
||||||
const size_t *pSteps;
|
const size_t *pSteps;
|
||||||
|
|
||||||
if(3 == uSteps)
|
if (3 == uSteps)
|
||||||
{
|
{
|
||||||
pSteps = pSteps3;
|
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.g = Step[1].g - Step[0].g;
|
||||||
Dir.b = Step[1].b - Step[0].b;
|
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;
|
float fScale = (wColorA != wColorB) ? (fSteps / (Dir.r * Dir.r + Dir.g * Dir.g + Dir.b * Dir.b)) : 0.0f;
|
||||||
|
|
||||||
Dir.r *= fScale;
|
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)
|
if (flags & BC_FLAGS_DITHER_RGB)
|
||||||
memset(Error, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(HDRColorA));
|
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);
|
dw = (3 << 30) | (dw >> 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HDRColorA Clr;
|
HDRColorA Clr;
|
||||||
if ( flags & BC_FLAGS_UNIFORM )
|
if (flags & BC_FLAGS_UNIFORM)
|
||||||
{
|
{
|
||||||
Clr.r = pColor[i].r;
|
Clr.r = pColor[i].r;
|
||||||
Clr.g = pColor[i].g;
|
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;
|
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;
|
uint32_t iStep;
|
||||||
|
|
||||||
if(fDot <= 0.0f)
|
if (fDot <= 0.0f)
|
||||||
iStep = 0;
|
iStep = 0;
|
||||||
else if(fDot >= fSteps)
|
else if (fDot >= fSteps)
|
||||||
iStep = 1;
|
iStep = 1;
|
||||||
else
|
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);
|
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.g = Color[i].a * (Clr.g - Step[iStep].g);
|
||||||
Diff.b = Color[i].a * (Clr.b - Step[iStep].b);
|
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].r += Diff.r * (7.0f / 16.0f);
|
||||||
Error[i + 1].g += Diff.g * (7.0f / 16.0f);
|
Error[i + 1].g += Diff.g * (7.0f / 16.0f);
|
||||||
Error[i + 1].b += Diff.b * (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].r += Diff.r * (3.0f / 16.0f);
|
||||||
Error[i + 3].g += Diff.g * (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].g += Diff.g * (5.0f / 16.0f);
|
||||||
Error[i + 4].b += Diff.b * (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].r += Diff.r * (1.0f / 16.0f);
|
||||||
Error[i + 5].g += Diff.g * (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;
|
pBC->bitmap = dw;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
#ifdef COLOR_WEIGHTS
|
#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
|
#ifdef COLOR_AVG_0WEIGHTS
|
||||||
// Compute avg color
|
// Compute avg color
|
||||||
HDRColorA 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.g = pColor[0].g;
|
||||||
Color.b = pColor[0].b;
|
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.r += pColor[i].r;
|
||||||
Color.g += pColor[i].g;
|
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[0] = wColor;
|
||||||
pBC->rgb[1] = wColor;
|
pBC->rgb[1] = wColor;
|
||||||
pBC->bitmap = 0x00000000;
|
pBC->bitmap = 0x00000000;
|
||||||
}
|
}
|
||||||
#endif // COLOR_WEIGHTS
|
#endif // COLOR_WEIGHTS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
@ -719,16 +728,16 @@ static void EncodeSolidBC1(_Out_ D3DX_BC1 *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK)
|
|||||||
// BC1 Compression
|
// BC1 Compression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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);
|
auto pBC1 = reinterpret_cast<const D3DX_BC1 *>(pBC);
|
||||||
DecodeBC1( pColor, pBC1, true );
|
DecodeBC1(pColor, pBC1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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];
|
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];
|
float fError[NUM_PIXELS_PER_BLOCK];
|
||||||
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
|
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;
|
HDRColorA clr;
|
||||||
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( &clr ), pColor[i] );
|
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(&clr), pColor[i]);
|
||||||
|
|
||||||
float fAlph = clr.a + fError[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;
|
float fDiff = fAlph - Color[i].a;
|
||||||
|
|
||||||
if(3 != (i & 3))
|
if (3 != (i & 3))
|
||||||
{
|
{
|
||||||
assert( i < 15 );
|
assert(i < 15);
|
||||||
_Analysis_assume_( i < 15 );
|
_Analysis_assume_(i < 15);
|
||||||
fError[i + 1] += fDiff * (7.0f / 16.0f);
|
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 + 3] += fDiff * (3.0f / 16.0f);
|
||||||
|
|
||||||
fError[i + 4] += fDiff * (5.0f / 16.0f);
|
fError[i + 4] += fDiff * (5.0f / 16.0f);
|
||||||
|
|
||||||
if(3 != (i & 3))
|
if (3 != (i & 3))
|
||||||
{
|
{
|
||||||
assert( i < 11 );
|
assert(i < 11);
|
||||||
_Analysis_assume_( i < 11 );
|
_Analysis_assume_(i < 11);
|
||||||
fError[i + 5] += fDiff * (1.0f / 16.0f);
|
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
|
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
|
// BC2 Compression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
|
void DirectX::D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
|
||||||
{
|
{
|
||||||
assert( pColor && pBC );
|
assert(pColor && pBC);
|
||||||
static_assert( sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes" );
|
static_assert(sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes");
|
||||||
|
|
||||||
auto pBC2 = reinterpret_cast<const D3DX_BC2 *>(pBC);
|
auto pBC2 = reinterpret_cast<const D3DX_BC2 *>(pBC);
|
||||||
|
|
||||||
@ -804,28 +813,28 @@ void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)
|
|||||||
// 4-bit alpha part
|
// 4-bit alpha part
|
||||||
DWORD dw = pBC2->bitmap[0];
|
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")
|
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||||
pColor[i] = XMVectorSetW( pColor[i], (float) (dw & 0xf) * (1.0f / 15.0f) );
|
pColor[i] = XMVectorSetW(pColor[i], (float)(dw & 0xf) * (1.0f / 15.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
dw = pBC2->bitmap[1];
|
dw = pBC2->bitmap[1];
|
||||||
|
|
||||||
for(size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 4)
|
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) );
|
pColor[i] = XMVectorSetW(pColor[i], (float)(dw & 0xf) * (1.0f / 15.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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 );
|
assert(pBC && pColor);
|
||||||
static_assert( sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes" );
|
static_assert(sizeof(D3DX_BC2) == 16, "D3DX_BC2 should be 16 bytes");
|
||||||
|
|
||||||
HDRColorA Color[NUM_PIXELS_PER_BLOCK];
|
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);
|
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)
|
if (flags & BC_FLAGS_DITHER_A)
|
||||||
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
|
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;
|
float fAlph = Color[i].a;
|
||||||
if (flags & BC_FLAGS_DITHER_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)
|
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 );
|
assert(i < 15);
|
||||||
_Analysis_assume_( i < 15 );
|
_Analysis_assume_(i < 15);
|
||||||
fError[i + 1] += fDiff * (7.0f / 16.0f);
|
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 + 3] += fDiff * (3.0f / 16.0f);
|
||||||
|
|
||||||
fError[i + 4] += fDiff * (5.0f / 16.0f);
|
fError[i + 4] += fDiff * (5.0f / 16.0f);
|
||||||
|
|
||||||
if(3 != (i & 3))
|
if (3 != (i & 3))
|
||||||
{
|
{
|
||||||
assert( i < 11 );
|
assert(i < 11);
|
||||||
_Analysis_assume_( i < 11 );
|
_Analysis_assume_(i < 11);
|
||||||
fError[i + 5] += fDiff * (1.0f / 16.0f);
|
fError[i + 5] += fDiff * (1.0f / 16.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -879,7 +888,7 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
|||||||
|
|
||||||
// RGB part
|
// RGB part
|
||||||
#ifdef COLOR_WEIGHTS
|
#ifdef COLOR_WEIGHTS
|
||||||
if(!pBC2->bitmap[0] && !pBC2->bitmap[1])
|
if (!pBC2->bitmap[0] && !pBC2->bitmap[1])
|
||||||
{
|
{
|
||||||
EncodeSolidBC1(pBC2->dxt1, Color);
|
EncodeSolidBC1(pBC2->dxt1, Color);
|
||||||
return;
|
return;
|
||||||
@ -894,10 +903,10 @@ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
|||||||
// BC3 Compression
|
// BC3 Compression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
|
void DirectX::D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
|
||||||
{
|
{
|
||||||
assert( pColor && pBC );
|
assert(pColor && pBC);
|
||||||
static_assert( sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes" );
|
static_assert(sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes");
|
||||||
|
|
||||||
auto pBC3 = reinterpret_cast<const D3DX_BC3 *>(pBC);
|
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
|
// Adaptive 3-bit alpha part
|
||||||
float fAlpha[8];
|
float fAlpha[8];
|
||||||
|
|
||||||
fAlpha[0] = ((float) pBC3->alpha[0]) * (1.0f / 255.0f);
|
fAlpha[0] = ((float)pBC3->alpha[0]) * (1.0f / 255.0f);
|
||||||
fAlpha[1] = ((float) pBC3->alpha[1]) * (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);
|
fAlpha[i + 1] = (fAlpha[0] * (7 - i) + fAlpha[1] * i) * (1.0f / 7.0f);
|
||||||
}
|
}
|
||||||
else
|
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[i + 1] = (fAlpha[0] * (5 - i) + fAlpha[1] * i) * (1.0f / 5.0f);
|
||||||
|
|
||||||
fAlpha[6] = 0.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);
|
DWORD dw = pBC3->bitmap[0] | (pBC3->bitmap[1] << 8) | (pBC3->bitmap[2] << 16);
|
||||||
|
|
||||||
for(size_t i = 0; i < 8; ++i, dw >>= 3)
|
for (size_t i = 0; i < 8; ++i, dw >>= 3)
|
||||||
pColor[i] = XMVectorSetW( pColor[i], fAlpha[dw & 0x7] );
|
pColor[i] = XMVectorSetW(pColor[i], fAlpha[dw & 0x7]);
|
||||||
|
|
||||||
dw = pBC3->bitmap[3] | (pBC3->bitmap[4] << 8) | (pBC3->bitmap[5] << 16);
|
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)
|
for (size_t i = 8; i < NUM_PIXELS_PER_BLOCK; ++i, dw >>= 3)
|
||||||
pColor[i] = XMVectorSetW( pColor[i], fAlpha[dw & 0x7] );
|
pColor[i] = XMVectorSetW(pColor[i], fAlpha[dw & 0x7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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 );
|
assert(pBC && pColor);
|
||||||
static_assert( sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes" );
|
static_assert(sizeof(D3DX_BC3) == 16, "D3DX_BC3 should be 16 bytes");
|
||||||
|
|
||||||
HDRColorA Color[NUM_PIXELS_PER_BLOCK];
|
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);
|
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)
|
if (flags & BC_FLAGS_DITHER_A)
|
||||||
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
|
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;
|
float fAlph = Color[i].a;
|
||||||
if (flags & BC_FLAGS_DITHER_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);
|
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];
|
fMinAlpha = fAlpha[i];
|
||||||
else if(fAlpha[i] > fMaxAlpha)
|
else if (fAlpha[i] > fMaxAlpha)
|
||||||
fMaxAlpha = fAlpha[i];
|
fMaxAlpha = fAlpha[i];
|
||||||
|
|
||||||
if (flags & BC_FLAGS_DITHER_A)
|
if (flags & BC_FLAGS_DITHER_A)
|
||||||
{
|
{
|
||||||
float fDiff = fAlph - fAlpha[i];
|
float fDiff = fAlph - fAlpha[i];
|
||||||
|
|
||||||
if(3 != (i & 3))
|
if (3 != (i & 3))
|
||||||
{
|
{
|
||||||
assert( i < 15 );
|
assert(i < 15);
|
||||||
_Analysis_assume_( i < 15 );
|
_Analysis_assume_(i < 15);
|
||||||
fError[i + 1] += fDiff * (7.0f / 16.0f);
|
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 + 3] += fDiff * (3.0f / 16.0f);
|
||||||
|
|
||||||
fError[i + 4] += fDiff * (5.0f / 16.0f);
|
fError[i + 4] += fDiff * (5.0f / 16.0f);
|
||||||
|
|
||||||
if(3 != (i & 3))
|
if (3 != (i & 3))
|
||||||
{
|
{
|
||||||
assert( i < 11 );
|
assert(i < 11);
|
||||||
_Analysis_assume_( i < 11 );
|
_Analysis_assume_(i < 11);
|
||||||
fError[i + 5] += fDiff * (1.0f / 16.0f);
|
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
|
#ifdef COLOR_WEIGHTS
|
||||||
if(0.0f == fMaxAlpha)
|
if (0.0f == fMaxAlpha)
|
||||||
{
|
{
|
||||||
EncodeSolidBC1(&pBC3->dxt1, Color);
|
EncodeSolidBC1(&pBC3->dxt1, Color);
|
||||||
pBC3->alpha[0] = 0x00;
|
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);
|
EncodeBC1(&pBC3->bc1, Color, false, 0.f, flags);
|
||||||
|
|
||||||
// Alpha part
|
// Alpha part
|
||||||
if(1.0f == fMinAlpha)
|
if (1.0f == fMinAlpha)
|
||||||
{
|
{
|
||||||
pBC3->alpha[0] = 0xff;
|
pBC3->alpha[0] = 0xff;
|
||||||
pBC3->alpha[1] = 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 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);
|
uint8_t bAlphaB = (uint8_t) static_cast<int32_t>(fAlphaB * 255.0f + 0.5f);
|
||||||
|
|
||||||
fAlphaA = (float) bAlphaA * (1.0f / 255.0f);
|
fAlphaA = (float)bAlphaA * (1.0f / 255.0f);
|
||||||
fAlphaB = (float) bAlphaB * (1.0f / 255.0f);
|
fAlphaB = (float)bAlphaB * (1.0f / 255.0f);
|
||||||
|
|
||||||
// Setup block
|
// Setup block
|
||||||
if((8 == uSteps) && (bAlphaA == bAlphaB))
|
if ((8 == uSteps) && (bAlphaA == bAlphaB))
|
||||||
{
|
{
|
||||||
pBC3->alpha[0] = bAlphaA;
|
pBC3->alpha[0] = bAlphaA;
|
||||||
pBC3->alpha[1] = bAlphaB;
|
pBC3->alpha[1] = bAlphaB;
|
||||||
@ -1051,7 +1060,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
|||||||
const size_t *pSteps;
|
const size_t *pSteps;
|
||||||
float fStep[8];
|
float fStep[8];
|
||||||
|
|
||||||
if(6 == uSteps)
|
if (6 == uSteps)
|
||||||
{
|
{
|
||||||
pBC3->alpha[0] = bAlphaA;
|
pBC3->alpha[0] = bAlphaA;
|
||||||
pBC3->alpha[1] = bAlphaB;
|
pBC3->alpha[1] = bAlphaB;
|
||||||
@ -1059,7 +1068,7 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
|||||||
fStep[0] = fAlphaA;
|
fStep[0] = fAlphaA;
|
||||||
fStep[1] = fAlphaB;
|
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[i + 1] = (fStep[0] * (5 - i) + fStep[1] * i) * (1.0f / 5.0f);
|
||||||
|
|
||||||
fStep[6] = 0.0f;
|
fStep[6] = 0.0f;
|
||||||
@ -1075,27 +1084,27 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
|||||||
fStep[0] = fAlphaB;
|
fStep[0] = fAlphaB;
|
||||||
fStep[1] = fAlphaA;
|
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);
|
fStep[i + 1] = (fStep[0] * (7 - i) + fStep[1] * i) * (1.0f / 7.0f);
|
||||||
|
|
||||||
pSteps = pSteps8;
|
pSteps = pSteps8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode alpha bitmap
|
// 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;
|
float fScale = (fStep[0] != fStep[1]) ? (fSteps / (fStep[1] - fStep[0])) : 0.0f;
|
||||||
|
|
||||||
if (flags & BC_FLAGS_DITHER_A)
|
if (flags & BC_FLAGS_DITHER_A)
|
||||||
memset(fError, 0x00, NUM_PIXELS_PER_BLOCK * sizeof(float));
|
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;
|
uint32_t dw = 0;
|
||||||
|
|
||||||
size_t iMin = iSet * 8;
|
size_t iMin = iSet * 8;
|
||||||
size_t iLim = iMin + 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;
|
float fAlph = Color[i].a;
|
||||||
if (flags & BC_FLAGS_DITHER_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;
|
float fDot = (fAlph - fStep[0]) * fScale;
|
||||||
|
|
||||||
uint32_t iStep;
|
uint32_t iStep;
|
||||||
if(fDot <= 0.0f)
|
if (fDot <= 0.0f)
|
||||||
iStep = ((6 == uSteps) && (fAlph <= fStep[0] * 0.5f)) ? 6 : 0;
|
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;
|
iStep = ((6 == uSteps) && (fAlph >= (fStep[1] + 1.0f) * 0.5f)) ? 7 : 1;
|
||||||
else
|
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);
|
dw = (iStep << 21) | (dw >> 3);
|
||||||
|
|
||||||
@ -1116,26 +1125,24 @@ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
|||||||
{
|
{
|
||||||
float fDiff = (fAlph - fStep[iStep]);
|
float fDiff = (fAlph - fStep[iStep]);
|
||||||
|
|
||||||
if(3 != (i & 3))
|
if (3 != (i & 3))
|
||||||
fError[i + 1] += fDiff * (7.0f / 16.0f);
|
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 + 3] += fDiff * (3.0f / 16.0f);
|
||||||
|
|
||||||
fError[i + 4] += fDiff * (5.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);
|
fError[i + 5] += fDiff * (1.0f / 16.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pBC3->bitmap[0 + iSet * 3] = ((uint8_t *) &dw)[0];
|
pBC3->bitmap[0 + iSet * 3] = ((uint8_t *)&dw)[0];
|
||||||
pBC3->bitmap[1 + iSet * 3] = ((uint8_t *) &dw)[1];
|
pBC3->bitmap[1 + iSet * 3] = ((uint8_t *)&dw)[1];
|
||||||
pBC3->bitmap[2 + iSet * 3] = ((uint8_t *) &dw)[2];
|
pBC3->bitmap[2 + iSet * 3] = ((uint8_t *)&dw)[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
@ -17,8 +17,7 @@
|
|||||||
|
|
||||||
#include "BC.h"
|
#include "BC.h"
|
||||||
|
|
||||||
namespace DirectX
|
using namespace DirectX;
|
||||||
{
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Constants
|
// Constants
|
||||||
@ -26,21 +25,23 @@ namespace DirectX
|
|||||||
|
|
||||||
// Because these are used in SAL annotations, they need to remain macros rather than const values
|
// Because these are used in SAL annotations, they need to remain macros rather than const values
|
||||||
#define BLOCK_LEN 4
|
#define BLOCK_LEN 4
|
||||||
// length of each block in texel
|
// length of each block in texel
|
||||||
|
|
||||||
#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN)
|
#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN)
|
||||||
// total texels in a 4x4 block.
|
// total texels in a 4x4 block.
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
namespace
|
||||||
// Structures
|
{
|
||||||
//-------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
// Structures
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4201)
|
#pragma warning(disable : 4201)
|
||||||
|
|
||||||
// BC4U/BC5U
|
// BC4U/BC5U
|
||||||
struct BC4_UNORM
|
struct BC4_UNORM
|
||||||
{
|
{
|
||||||
float R(size_t uOffset) const
|
float R(size_t uOffset) const
|
||||||
{
|
{
|
||||||
size_t uIndex = GetIndex(uOffset);
|
size_t uIndex = GetIndex(uOffset);
|
||||||
@ -58,7 +59,7 @@ struct BC4_UNORM
|
|||||||
if (red_0 > red_1)
|
if (red_0 > red_1)
|
||||||
{
|
{
|
||||||
uIndex -= 1;
|
uIndex -= 1;
|
||||||
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
|
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -67,19 +68,19 @@ struct BC4_UNORM
|
|||||||
if (uIndex == 7)
|
if (uIndex == 7)
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
uIndex -= 1;
|
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
|
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)
|
void SetIndex(size_t uOffset, size_t uIndex)
|
||||||
{
|
{
|
||||||
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
|
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
|
||||||
data |= ((uint64_t) uIndex << (3*uOffset + 16));
|
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
union
|
union
|
||||||
@ -92,11 +93,11 @@ struct BC4_UNORM
|
|||||||
};
|
};
|
||||||
uint64_t data;
|
uint64_t data;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// BC4S/BC5S
|
// BC4S/BC5S
|
||||||
struct BC4_SNORM
|
struct BC4_SNORM
|
||||||
{
|
{
|
||||||
float R(size_t uOffset) const
|
float R(size_t uOffset) const
|
||||||
{
|
{
|
||||||
size_t uIndex = GetIndex(uOffset);
|
size_t uIndex = GetIndex(uOffset);
|
||||||
@ -105,8 +106,8 @@ struct BC4_SNORM
|
|||||||
|
|
||||||
float DecodeFromIndex(size_t uIndex) const
|
float DecodeFromIndex(size_t uIndex) const
|
||||||
{
|
{
|
||||||
int8_t sred_0 = (red_0 == -128)? -127 : red_0;
|
int8_t sred_0 = (red_0 == -128) ? -127 : red_0;
|
||||||
int8_t sred_1 = (red_1 == -128)? -127 : red_1;
|
int8_t sred_1 = (red_1 == -128) ? -127 : red_1;
|
||||||
|
|
||||||
if (uIndex == 0)
|
if (uIndex == 0)
|
||||||
return sred_0 / 127.0f;
|
return sred_0 / 127.0f;
|
||||||
@ -117,7 +118,7 @@ struct BC4_SNORM
|
|||||||
if (red_0 > red_1)
|
if (red_0 > red_1)
|
||||||
{
|
{
|
||||||
uIndex -= 1;
|
uIndex -= 1;
|
||||||
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
|
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -126,19 +127,19 @@ struct BC4_SNORM
|
|||||||
if (uIndex == 7)
|
if (uIndex == 7)
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
uIndex -= 1;
|
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
|
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)
|
void SetIndex(size_t uOffset, size_t uIndex)
|
||||||
{
|
{
|
||||||
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
|
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
|
||||||
data |= ((uint64_t) uIndex << (3*uOffset + 16));
|
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
union
|
union
|
||||||
@ -151,40 +152,43 @@ struct BC4_SNORM
|
|||||||
};
|
};
|
||||||
uint64_t data;
|
uint64_t data;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Convert a floating point value to an 8-bit SNORM
|
// Convert a floating point value to an 8-bit SNORM
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static void inline FloatToSNorm( _In_ float fVal, _Out_ int8_t *piSNorm )
|
void inline FloatToSNorm(_In_ float fVal, _Out_ int8_t *piSNorm)
|
||||||
{
|
{
|
||||||
const uint32_t dwMostNeg = ( 1 << ( 8 * sizeof( int8_t ) - 1 ) );
|
const uint32_t dwMostNeg = (1 << (8 * sizeof(int8_t) - 1));
|
||||||
|
|
||||||
if( _isnan( fVal ) )
|
if (_isnan(fVal))
|
||||||
fVal = 0;
|
fVal = 0;
|
||||||
else
|
else
|
||||||
if( fVal > 1 )
|
if (fVal > 1)
|
||||||
fVal = 1; // Clamp to 1
|
fVal = 1; // Clamp to 1
|
||||||
else
|
else
|
||||||
if( fVal < -1 )
|
if (fVal < -1)
|
||||||
fVal = -1; // Clamp to -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;
|
fVal += .5f;
|
||||||
else
|
else
|
||||||
fVal -= .5f;
|
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
|
// The boundary of codec for signed/unsigned format
|
||||||
float MIN_NORM;
|
float MIN_NORM;
|
||||||
float MAX_NORM = 1.0f;
|
float MAX_NORM = 1.0f;
|
||||||
@ -198,11 +202,11 @@ static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[],
|
|||||||
float fBlockMin = theTexelsU[0];
|
float fBlockMin = theTexelsU[0];
|
||||||
for (i = 0; i < BLOCK_SIZE; ++i)
|
for (i = 0; i < BLOCK_SIZE; ++i)
|
||||||
{
|
{
|
||||||
if (theTexelsU[i]<fBlockMin)
|
if (theTexelsU[i] < fBlockMin)
|
||||||
{
|
{
|
||||||
fBlockMin = theTexelsU[i];
|
fBlockMin = theTexelsU[i];
|
||||||
}
|
}
|
||||||
else if (theTexelsU[i]>fBlockMax)
|
else if (theTexelsU[i] > fBlockMax)
|
||||||
{
|
{
|
||||||
fBlockMax = theTexelsU[i];
|
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
|
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
|
||||||
// the exact code of the boundary values.
|
// 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
|
// Using Optimize
|
||||||
float fStart, fEnd;
|
float fStart, fEnd;
|
||||||
@ -219,8 +223,8 @@ static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[],
|
|||||||
{
|
{
|
||||||
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
|
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
|
||||||
|
|
||||||
iStart = (uint8_t) (fStart * 255.0f);
|
iStart = (uint8_t)(fStart * 255.0f);
|
||||||
iEnd = (uint8_t) (fEnd * 255.0f);
|
iEnd = (uint8_t)(fEnd * 255.0f);
|
||||||
|
|
||||||
endpointU_0 = iEnd;
|
endpointU_0 = iEnd;
|
||||||
endpointU_1 = iStart;
|
endpointU_1 = iStart;
|
||||||
@ -229,16 +233,19 @@ static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[],
|
|||||||
{
|
{
|
||||||
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
|
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
|
||||||
|
|
||||||
iStart = (uint8_t) (fStart * 255.0f);
|
iStart = (uint8_t)(fStart * 255.0f);
|
||||||
iEnd = (uint8_t) (fEnd * 255.0f);
|
iEnd = (uint8_t)(fEnd * 255.0f);
|
||||||
|
|
||||||
endpointU_1 = iEnd;
|
endpointU_1 = iEnd;
|
||||||
endpointU_0 = iStart;
|
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
|
// The boundary of codec for signed/unsigned format
|
||||||
float MIN_NORM;
|
float MIN_NORM;
|
||||||
float MAX_NORM = 1.0f;
|
float MAX_NORM = 1.0f;
|
||||||
@ -252,11 +259,11 @@ static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _
|
|||||||
float fBlockMin = theTexelsU[0];
|
float fBlockMin = theTexelsU[0];
|
||||||
for (i = 0; i < BLOCK_SIZE; ++i)
|
for (i = 0; i < BLOCK_SIZE; ++i)
|
||||||
{
|
{
|
||||||
if (theTexelsU[i]<fBlockMin)
|
if (theTexelsU[i] < fBlockMin)
|
||||||
{
|
{
|
||||||
fBlockMin = theTexelsU[i];
|
fBlockMin = theTexelsU[i];
|
||||||
}
|
}
|
||||||
else if (theTexelsU[i]>fBlockMax)
|
else if (theTexelsU[i] > fBlockMax)
|
||||||
{
|
{
|
||||||
fBlockMax = theTexelsU[i];
|
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
|
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
|
||||||
// the exact code of the boundary values.
|
// 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
|
// Using Optimize
|
||||||
float fStart, fEnd;
|
float fStart, fEnd;
|
||||||
@ -289,30 +296,42 @@ static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _
|
|||||||
endpointU_1 = iEnd;
|
endpointU_1 = iEnd;
|
||||||
endpointU_0 = iStart;
|
endpointU_0 = iStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
static inline void FindEndPointsBC5U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
|
inline void FindEndPointsBC5U(
|
||||||
_Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1, _Out_ uint8_t &endpointV_0, _Out_ uint8_t &endpointV_1)
|
_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.
|
//Encoding the U and V channel by BC4 codec separately.
|
||||||
FindEndPointsBC4U( theTexelsU, endpointU_0, endpointU_1);
|
FindEndPointsBC4U(theTexelsU, endpointU_0, endpointU_1);
|
||||||
FindEndPointsBC4U( theTexelsV, endpointV_0, endpointV_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[],
|
inline void FindEndPointsBC5S(
|
||||||
_Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1, _Out_ int8_t &endpointV_0, _Out_ int8_t &endpointV_1)
|
_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.
|
//Encoding the U and V channel by BC4 codec separately.
|
||||||
FindEndPointsBC4S( theTexelsU, endpointU_0, endpointU_1);
|
FindEndPointsBC4S(theTexelsU, endpointU_0, endpointU_1);
|
||||||
FindEndPointsBC4S( theTexelsV, endpointV_0, endpointV_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];
|
float rGradient[8];
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 8; ++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;
|
float fBestDelta = 100000;
|
||||||
for (size_t uIndex = 0; uIndex < 8; uIndex++)
|
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)
|
if (fCurrentDelta < fBestDelta)
|
||||||
{
|
{
|
||||||
uBestIndex = uIndex;
|
uBestIndex = uIndex;
|
||||||
@ -334,10 +353,12 @@ static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
|
|||||||
}
|
}
|
||||||
pBC->SetIndex(i, uBestIndex);
|
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];
|
float rGradient[8];
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 8; ++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;
|
float fBestDelta = 100000;
|
||||||
for (size_t uIndex = 0; uIndex < 8; uIndex++)
|
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)
|
if (fCurrentDelta < fBestDelta)
|
||||||
{
|
{
|
||||||
uBestIndex = uIndex;
|
uBestIndex = uIndex;
|
||||||
@ -359,6 +380,7 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
|
|||||||
}
|
}
|
||||||
pBC->SetIndex(i, uBestIndex);
|
pBC->SetIndex(i, uBestIndex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -370,42 +392,42 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
|
|||||||
// BC4 Compression
|
// BC4 Compression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void D3DXDecodeBC4U( XMVECTOR *pColor, const uint8_t *pBC )
|
void DirectX::D3DXDecodeBC4U(XMVECTOR *pColor, const uint8_t *pBC)
|
||||||
{
|
{
|
||||||
assert( pColor && pBC );
|
assert(pColor && pBC);
|
||||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
|
||||||
|
|
||||||
auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
|
auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
|
||||||
|
|
||||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
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( pBC4->R(i), 0, 0, 1.0f);
|
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
|
void DirectX::D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
|
||||||
{
|
{
|
||||||
assert( pColor && pBC );
|
assert(pColor && pBC);
|
||||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
|
||||||
|
|
||||||
auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
|
auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
|
||||||
|
|
||||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
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( pBC4->R(i), 0, 0, 1.0f);
|
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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 );
|
assert(pBC && pColor);
|
||||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
|
||||||
|
|
||||||
memset(pBC, 0, sizeof(BC4_UNORM));
|
memset(pBC, 0, sizeof(BC4_UNORM));
|
||||||
auto pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
|
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)
|
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);
|
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_
|
_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 );
|
assert(pBC && pColor);
|
||||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
|
||||||
|
|
||||||
memset(pBC, 0, sizeof(BC4_UNORM));
|
memset(pBC, 0, sizeof(BC4_UNORM));
|
||||||
auto pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
|
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)
|
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);
|
FindEndPointsBC4S(theTexelsU, pBC4->red_0, pBC4->red_1);
|
||||||
@ -446,55 +468,55 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
|||||||
// BC5 Compression
|
// BC5 Compression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
|
void DirectX::D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
|
||||||
{
|
{
|
||||||
assert( pColor && pBC );
|
assert(pColor && pBC);
|
||||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
|
||||||
|
|
||||||
auto pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
|
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)
|
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);
|
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
|
void DirectX::D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
|
||||||
{
|
{
|
||||||
assert( pColor && pBC );
|
assert(pColor && pBC);
|
||||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
|
||||||
|
|
||||||
auto pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
|
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)
|
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);
|
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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 );
|
assert(pBC && pColor);
|
||||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
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 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 theTexelsU[NUM_PIXELS_PER_BLOCK];
|
||||||
float theTexelsV[NUM_PIXELS_PER_BLOCK];
|
float theTexelsV[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)
|
||||||
{
|
{
|
||||||
XMFLOAT4A clr;
|
XMFLOAT4A clr;
|
||||||
XMStoreFloat4A( &clr, pColor[i] );
|
XMStoreFloat4A(&clr, pColor[i]);
|
||||||
theTexelsU[i] = clr.x;
|
theTexelsU[i] = clr.x;
|
||||||
theTexelsV[i] = clr.y;
|
theTexelsV[i] = clr.y;
|
||||||
}
|
}
|
||||||
@ -512,23 +534,23 @@ void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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 );
|
assert(pBC && pColor);
|
||||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
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 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 theTexelsU[NUM_PIXELS_PER_BLOCK];
|
||||||
float theTexelsV[NUM_PIXELS_PER_BLOCK];
|
float theTexelsV[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)
|
||||||
{
|
{
|
||||||
XMFLOAT4A clr;
|
XMFLOAT4A clr;
|
||||||
XMStoreFloat4A( &clr, pColor[i] );
|
XMStoreFloat4A(&clr, pColor[i]);
|
||||||
theTexelsU[i] = clr.x;
|
theTexelsU[i] = clr.x;
|
||||||
theTexelsV[i] = clr.y;
|
theTexelsV[i] = clr.y;
|
||||||
}
|
}
|
||||||
@ -544,5 +566,3 @@ void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
|||||||
FindClosestSNORM(pBCR, theTexelsU);
|
FindClosestSNORM(pBCR, theTexelsU);
|
||||||
FindClosestSNORM(pBCG, theTexelsV);
|
FindClosestSNORM(pBCG, theTexelsV);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@
|
|||||||
#pragma comment(lib,"dxguid.lib")
|
#pragma comment(lib,"dxguid.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace DirectX;
|
||||||
using Microsoft::WRL::ComPtr;
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -82,9 +83,6 @@ namespace
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace DirectX
|
|
||||||
{
|
|
||||||
|
|
||||||
GPUCompressBC::GPUCompressBC() :
|
GPUCompressBC::GPUCompressBC() :
|
||||||
m_bcformat(DXGI_FORMAT_UNKNOWN),
|
m_bcformat(DXGI_FORMAT_UNKNOWN),
|
||||||
m_srcformat(DXGI_FORMAT_UNKNOWN),
|
m_srcformat(DXGI_FORMAT_UNKNOWN),
|
||||||
@ -97,79 +95,79 @@ GPUCompressBC::GPUCompressBC() :
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
|
HRESULT GPUCompressBC::Initialize(ID3D11Device* pDevice)
|
||||||
{
|
{
|
||||||
if ( !pDevice )
|
if (!pDevice)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
// Check for DirectCompute support
|
// Check for DirectCompute support
|
||||||
D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel();
|
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
|
// 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
|
// DirectCompute support on Feature Level 10.x hardware is optional, and this function needs it
|
||||||
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts;
|
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts;
|
||||||
HRESULT hr = pDevice->CheckFeatureSupport( D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) );
|
HRESULT hr = pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts));
|
||||||
if ( FAILED(hr) )
|
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
|
// Save a device reference and obtain immediate context
|
||||||
m_device = pDevice;
|
m_device = pDevice;
|
||||||
|
|
||||||
pDevice->GetImmediateContext( m_context.ReleaseAndGetAddressOf() );
|
pDevice->GetImmediateContext(m_context.ReleaseAndGetAddressOf());
|
||||||
assert( m_context );
|
assert(m_context);
|
||||||
|
|
||||||
//--- Create compute shader library: BC6H -----------------------------------------
|
//--- Create compute shader library: BC6H -----------------------------------------
|
||||||
|
|
||||||
// Modes 11-14
|
// Modes 11-14
|
||||||
HRESULT hr = pDevice->CreateComputeShader( BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf() );
|
HRESULT hr = pDevice->CreateComputeShader(BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Modes 1-10
|
// Modes 1-10
|
||||||
hr = pDevice->CreateComputeShader( BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateComputeShader(BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Encode
|
// Encode
|
||||||
hr = pDevice->CreateComputeShader( BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateComputeShader(BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
//--- Create compute shader library: BC7 ------------------------------------------
|
//--- Create compute shader library: BC7 ------------------------------------------
|
||||||
|
|
||||||
// Modes 4, 5, 6
|
// Modes 4, 5, 6
|
||||||
hr = pDevice->CreateComputeShader( BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateComputeShader(BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Modes 1, 3, 7
|
// Modes 1, 3, 7
|
||||||
hr = pDevice->CreateComputeShader( BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateComputeShader(BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Modes 0, 2
|
// Modes 0, 2
|
||||||
hr = pDevice->CreateComputeShader( BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateComputeShader(BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Encode
|
// Encode
|
||||||
hr = pDevice->CreateComputeShader( BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateComputeShader(BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@ -178,12 +176,12 @@ HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( (width > UINT32_MAX) || (height > UINT32_MAX) )
|
if ((width > UINT32_MAX) || (height > UINT32_MAX))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
m_width = width;
|
m_width = width;
|
||||||
@ -193,11 +191,11 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
|||||||
|
|
||||||
m_skip3Subsets = skip3subsets;
|
m_skip3Subsets = skip3subsets;
|
||||||
|
|
||||||
size_t xblocks = std::max<size_t>( 1, (width + 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 yblocks = std::max<size_t>(1, (height + 3) >> 2);
|
||||||
size_t num_blocks = xblocks * yblocks;
|
size_t num_blocks = xblocks * yblocks;
|
||||||
|
|
||||||
switch( format )
|
switch (format)
|
||||||
{
|
{
|
||||||
// BC6H GPU compressor takes RGBAF32 as input
|
// BC6H GPU compressor takes RGBAF32 as input
|
||||||
case DXGI_FORMAT_BC6H_TYPELESS:
|
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||||
@ -218,39 +216,39 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN;
|
m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN;
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bcformat = format;
|
m_bcformat = format;
|
||||||
|
|
||||||
auto pDevice = m_device.Get();
|
auto pDevice = m_device.Get();
|
||||||
if ( !pDevice )
|
if (!pDevice)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
// Create structured buffers
|
// Create structured buffers
|
||||||
size_t bufferSize = num_blocks * sizeof( BufferBC6HBC7 );
|
size_t bufferSize = num_blocks * sizeof(BufferBC6HBC7);
|
||||||
{
|
{
|
||||||
D3D11_BUFFER_DESC desc = {};
|
D3D11_BUFFER_DESC desc = {};
|
||||||
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
||||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
||||||
desc.StructureByteStride = sizeof( BufferBC6HBC7 );
|
desc.StructureByteStride = sizeof(BufferBC6HBC7);
|
||||||
desc.ByteWidth = static_cast<UINT>( bufferSize );
|
desc.ByteWidth = static_cast<UINT>(bufferSize);
|
||||||
|
|
||||||
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_output.ReleaseAndGetAddressOf() );
|
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_output.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pDevice->CreateBuffer( &desc, nullptr, m_err1.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateBuffer(&desc, nullptr, m_err1.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pDevice->CreateBuffer( &desc, nullptr, m_err2.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateBuffer(&desc, nullptr, m_err2.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -261,10 +259,10 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
|||||||
D3D11_BUFFER_DESC desc = {};
|
D3D11_BUFFER_DESC desc = {};
|
||||||
desc.Usage = D3D11_USAGE_STAGING;
|
desc.Usage = D3D11_USAGE_STAGING;
|
||||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
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() );
|
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return 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.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
desc.ByteWidth = sizeof( ConstantsBC6HBC7 );
|
desc.ByteWidth = sizeof(ConstantsBC6HBC7);
|
||||||
|
|
||||||
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf() );
|
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -288,17 +286,17 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
|||||||
// Create shader resource views
|
// Create shader resource views
|
||||||
{
|
{
|
||||||
D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
|
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;
|
desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||||
|
|
||||||
HRESULT hr = pDevice->CreateShaderResourceView( m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf() );
|
HRESULT hr = pDevice->CreateShaderResourceView(m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pDevice->CreateShaderResourceView( m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateShaderResourceView(m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -307,23 +305,23 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
|||||||
// Create unordered access views
|
// Create unordered access views
|
||||||
{
|
{
|
||||||
D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
|
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;
|
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
||||||
|
|
||||||
HRESULT hr = pDevice->CreateUnorderedAccessView( m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf() );
|
HRESULT hr = pDevice->CreateUnorderedAccessView(m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pDevice->CreateUnorderedAccessView( m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateUnorderedAccessView(m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pDevice->CreateUnorderedAccessView( m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf() );
|
hr = pDevice->CreateUnorderedAccessView(m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -335,34 +333,34 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( srcImage.width != destImage.width
|
if (srcImage.width != destImage.width
|
||||||
|| srcImage.height != destImage.height
|
|| srcImage.height != destImage.height
|
||||||
|| srcImage.width != m_width
|
|| srcImage.width != m_width
|
||||||
|| srcImage.height != m_height
|
|| srcImage.height != m_height
|
||||||
|| srcImage.format != m_srcformat
|
|| srcImage.format != m_srcformat
|
||||||
|| destImage.format != m_bcformat )
|
|| destImage.format != m_bcformat)
|
||||||
{
|
{
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
//--- Create input texture --------------------------------------------------------
|
//--- Create input texture --------------------------------------------------------
|
||||||
auto pDevice = m_device.Get();
|
auto pDevice = m_device.Get();
|
||||||
if ( !pDevice )
|
if (!pDevice)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
// We need to avoid the hardware doing additional colorspace conversion
|
// 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;
|
ComPtr<ID3D11Texture2D> sourceTex;
|
||||||
{
|
{
|
||||||
D3D11_TEXTURE2D_DESC desc = {};
|
D3D11_TEXTURE2D_DESC desc = {};
|
||||||
desc.Width = static_cast<UINT>( srcImage.width );
|
desc.Width = static_cast<UINT>(srcImage.width);
|
||||||
desc.Height = static_cast<UINT>( srcImage.height );
|
desc.Height = static_cast<UINT>(srcImage.height);
|
||||||
desc.MipLevels = 1;
|
desc.MipLevels = 1;
|
||||||
desc.ArraySize = 1;
|
desc.ArraySize = 1;
|
||||||
desc.Format = inputFormat;
|
desc.Format = inputFormat;
|
||||||
@ -372,11 +370,11 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
|||||||
|
|
||||||
D3D11_SUBRESOURCE_DATA initData;
|
D3D11_SUBRESOURCE_DATA initData;
|
||||||
initData.pSysMem = srcImage.pixels;
|
initData.pSysMem = srcImage.pixels;
|
||||||
initData.SysMemPitch = static_cast<DWORD>( srcImage.rowPitch );
|
initData.SysMemPitch = static_cast<DWORD>(srcImage.rowPitch);
|
||||||
initData.SysMemSlicePitch = static_cast<DWORD>( srcImage.slicePitch );
|
initData.SysMemSlicePitch = static_cast<DWORD>(srcImage.slicePitch);
|
||||||
|
|
||||||
HRESULT hr = pDevice->CreateTexture2D( &desc, &initData, sourceTex.GetAddressOf() );
|
HRESULT hr = pDevice->CreateTexture2D(&desc, &initData, sourceTex.GetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -389,8 +387,8 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
|||||||
desc.Format = inputFormat;
|
desc.Format = inputFormat;
|
||||||
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
|
||||||
HRESULT hr = pDevice->CreateShaderResourceView( sourceTex.Get(), &desc, sourceSRV.GetAddressOf() );
|
HRESULT hr = pDevice->CreateShaderResourceView(sourceTex.Get(), &desc, sourceSRV.GetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -398,7 +396,7 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
|||||||
|
|
||||||
//--- Compress using DirectCompute ------------------------------------------------
|
//--- Compress using DirectCompute ------------------------------------------------
|
||||||
bool isbc7 = false;
|
bool isbc7 = false;
|
||||||
switch( m_bcformat )
|
switch (m_bcformat)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_BC6H_TYPELESS:
|
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||||
case DXGI_FORMAT_BC6H_UF16:
|
case DXGI_FORMAT_BC6H_UF16:
|
||||||
@ -418,47 +416,47 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
|||||||
const UINT MAX_BLOCK_BATCH = 64;
|
const UINT MAX_BLOCK_BATCH = 64;
|
||||||
|
|
||||||
auto pContext = m_context.Get();
|
auto pContext = m_context.Get();
|
||||||
if ( !pContext )
|
if (!pContext)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
size_t xblocks = std::max<size_t>( 1, (m_width + 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 );
|
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;
|
UINT num_blocks = num_total_blocks;
|
||||||
int start_block_id = 0;
|
int start_block_id = 0;
|
||||||
while (num_blocks > 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;
|
UINT uThreadGroupCount = n;
|
||||||
|
|
||||||
{
|
{
|
||||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
ConstantsBC6HBC7 param;
|
ConstantsBC6HBC7 param;
|
||||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||||
param.num_block_x = static_cast<UINT>( xblocks );
|
param.num_block_x = static_cast<UINT>(xblocks);
|
||||||
param.format = m_bcformat;
|
param.format = m_bcformat;
|
||||||
param.mode_id = 0;
|
param.mode_id = 0;
|
||||||
param.start_block_id = start_block_id;
|
param.start_block_id = start_block_id;
|
||||||
param.num_total_blocks = num_total_blocks;
|
param.num_total_blocks = num_total_blocks;
|
||||||
param.alpha_weight = m_alphaWeight;
|
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 -----------------------------------------------------------------
|
//--- BC7 -----------------------------------------------------------------
|
||||||
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
|
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
|
||||||
RunComputeShader( pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
RunComputeShader(pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||||
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
|
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 };
|
static const UINT modes[] = { 1, 3, 7 };
|
||||||
|
|
||||||
@ -467,141 +465,139 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
|||||||
// Mode 7: err1 -> err2
|
// Mode 7: err1 -> err2
|
||||||
{
|
{
|
||||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
ResetContext( pContext );
|
ResetContext(pContext);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantsBC6HBC7 param;
|
ConstantsBC6HBC7 param;
|
||||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||||
param.num_block_x = static_cast<UINT>( xblocks );
|
param.num_block_x = static_cast<UINT>(xblocks);
|
||||||
param.format = m_bcformat;
|
param.format = m_bcformat;
|
||||||
param.mode_id = modes[i];
|
param.mode_id = modes[i];
|
||||||
param.start_block_id = start_block_id;
|
param.start_block_id = start_block_id;
|
||||||
param.num_total_blocks = num_total_blocks;
|
param.num_total_blocks = num_total_blocks;
|
||||||
param.alpha_weight = m_alphaWeight;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
|
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
|
||||||
RunComputeShader( pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
RunComputeShader(pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||||
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount );
|
(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
|
// 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 };
|
static const UINT modes[] = { 0, 2 };
|
||||||
// Mode 0: err2 -> err1
|
// Mode 0: err2 -> err1
|
||||||
// Mode 2: err1 -> err2
|
// Mode 2: err1 -> err2
|
||||||
{
|
{
|
||||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
ResetContext( pContext );
|
ResetContext(pContext);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantsBC6HBC7 param;
|
ConstantsBC6HBC7 param;
|
||||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||||
param.num_block_x = static_cast<UINT>( xblocks );
|
param.num_block_x = static_cast<UINT>(xblocks);
|
||||||
param.format = m_bcformat;
|
param.format = m_bcformat;
|
||||||
param.mode_id = modes[i];
|
param.mode_id = modes[i];
|
||||||
param.start_block_id = start_block_id;
|
param.start_block_id = start_block_id;
|
||||||
param.num_total_blocks = num_total_blocks;
|
param.num_total_blocks = num_total_blocks;
|
||||||
param.alpha_weight = m_alphaWeight;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get();
|
pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get();
|
||||||
RunComputeShader( pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
RunComputeShader(pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||||
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount );
|
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pSRVs[1] = m_err2SRV.Get();
|
pSRVs[1] = m_err2SRV.Get();
|
||||||
RunComputeShader( pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
RunComputeShader(pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||||
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
|
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//--- BC6H ----------------------------------------------------------------
|
//--- BC6H ----------------------------------------------------------------
|
||||||
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
|
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
|
||||||
RunComputeShader( pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
RunComputeShader(pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||||
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
|
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;
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
ResetContext( pContext );
|
ResetContext(pContext);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantsBC6HBC7 param;
|
ConstantsBC6HBC7 param;
|
||||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||||
param.num_block_x = static_cast<UINT>( xblocks );
|
param.num_block_x = static_cast<UINT>(xblocks);
|
||||||
param.format = m_bcformat;
|
param.format = m_bcformat;
|
||||||
param.mode_id = i;
|
param.mode_id = i;
|
||||||
param.start_block_id = start_block_id;
|
param.start_block_id = start_block_id;
|
||||||
param.num_total_blocks = num_total_blocks;
|
param.num_total_blocks = num_total_blocks;
|
||||||
memcpy( mapped.pData, ¶m, sizeof( param ) );
|
memcpy(mapped.pData, ¶m, sizeof(param));
|
||||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
pContext->Unmap(m_constBuffer.Get(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
|
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
|
||||||
RunComputeShader( pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.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) );
|
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
pSRVs[1] = m_err1SRV.Get();
|
pSRVs[1] = m_err1SRV.Get();
|
||||||
RunComputeShader( pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
RunComputeShader(pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||||
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
|
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
start_block_id += n;
|
start_block_id += n;
|
||||||
num_blocks -= n;
|
num_blocks -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetContext( pContext );
|
ResetContext(pContext);
|
||||||
|
|
||||||
//--- Copy output texture back to CPU ---------------------------------------------
|
//--- 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;
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||||
HRESULT hr = pContext->Map( m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped );
|
HRESULT hr = pContext->Map(m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped);
|
||||||
if ( SUCCEEDED(hr) )
|
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;
|
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;
|
pSrc += pitch;
|
||||||
pDest += destImage.rowPitch;
|
pDest += destImage.rowPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
pContext->Unmap( m_outputCPU.Get(), 0 );
|
pContext->Unmap(m_outputCPU.Get(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
#include <ocidl.h>
|
#include <ocidl.h>
|
||||||
|
|
||||||
#define DIRECTX_TEX_VERSION 134
|
#define DIRECTX_TEX_VERSION 140
|
||||||
|
|
||||||
struct IWICImagingFactory;
|
struct IWICImagingFactory;
|
||||||
struct IWICMetadataQueryReader;
|
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)
|
// 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 );
|
_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 );
|
_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 );
|
_Out_ TexMetadata& metadata );
|
||||||
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
|
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ const wchar_t* szFile,
|
||||||
_Out_ TexMetadata& metadata );
|
_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,
|
_Out_ TexMetadata& metadata,
|
||||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
_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,
|
_Out_ TexMetadata& metadata,
|
||||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
||||||
|
|
||||||
@ -238,13 +238,16 @@ namespace DirectX
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScratchImage()
|
ScratchImage()
|
||||||
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) {}
|
: m_nimages(0), m_size(0), m_image(nullptr), m_memory(nullptr) {}
|
||||||
ScratchImage(ScratchImage&& moveFrom)
|
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() { Release(); }
|
||||||
|
|
||||||
ScratchImage& __cdecl operator= (ScratchImage&& moveFrom);
|
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 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 );
|
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 );
|
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 GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const;
|
||||||
|
|
||||||
const Image* __cdecl GetImages() const { return _image; }
|
const Image* __cdecl GetImages() const { return m_image; }
|
||||||
size_t __cdecl GetImageCount() const { return _nimages; }
|
size_t __cdecl GetImageCount() const { return m_nimages; }
|
||||||
|
|
||||||
uint8_t* __cdecl GetPixels() const { return _memory; }
|
uint8_t* __cdecl GetPixels() const { return m_memory; }
|
||||||
size_t __cdecl GetPixelsSize() const { return _size; }
|
size_t __cdecl GetPixelsSize() const { return m_size; }
|
||||||
|
|
||||||
bool __cdecl IsAlphaAllOpaque() const;
|
bool __cdecl IsAlphaAllOpaque() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t _nimages;
|
size_t m_nimages;
|
||||||
size_t _size;
|
size_t m_size;
|
||||||
TexMetadata _metadata;
|
TexMetadata m_metadata;
|
||||||
Image* _image;
|
Image* m_image;
|
||||||
uint8_t* _memory;
|
uint8_t* m_memory;
|
||||||
|
|
||||||
// Hide copy constructor and assignment operator
|
|
||||||
ScratchImage( const ScratchImage& );
|
|
||||||
ScratchImage& operator=( const ScratchImage& );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
@ -289,35 +288,34 @@ namespace DirectX
|
|||||||
class Blob
|
class Blob
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Blob() : _buffer(nullptr), _size(0) {}
|
Blob() : m_buffer(nullptr), m_size(0) {}
|
||||||
Blob(Blob&& moveFrom) : _buffer(nullptr), _size(0) { *this = std::move(moveFrom); }
|
Blob(Blob&& moveFrom) : m_buffer(nullptr), m_size(0) { *this = std::move(moveFrom); }
|
||||||
~Blob() { Release(); }
|
~Blob() { Release(); }
|
||||||
|
|
||||||
Blob& __cdecl operator= (Blob&& moveFrom);
|
Blob& __cdecl operator= (Blob&& moveFrom);
|
||||||
|
|
||||||
|
Blob(const Blob&) = delete;
|
||||||
|
Blob& operator=(const Blob&) = delete;
|
||||||
|
|
||||||
HRESULT __cdecl Initialize( _In_ size_t size );
|
HRESULT __cdecl Initialize( _In_ size_t size );
|
||||||
|
|
||||||
void __cdecl Release();
|
void __cdecl Release();
|
||||||
|
|
||||||
void *__cdecl GetBufferPointer() const { return _buffer; }
|
void *__cdecl GetBufferPointer() const { return m_buffer; }
|
||||||
size_t __cdecl GetBufferSize() const { return _size; }
|
size_t __cdecl GetBufferSize() const { return m_size; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* _buffer;
|
void* m_buffer;
|
||||||
size_t _size;
|
size_t m_size;
|
||||||
|
|
||||||
// Hide copy constructor and assignment operator
|
|
||||||
Blob( const Blob& );
|
|
||||||
Blob& operator=( const Blob& );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
// Image I/O
|
// Image I/O
|
||||||
|
|
||||||
// DDS operations
|
// 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 );
|
_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 );
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
|
||||||
|
|
||||||
HRESULT __cdecl SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags,
|
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,
|
HRESULT __cdecl SaveToDDSMemory( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags,
|
||||||
_Out_ Blob& blob );
|
_Out_ Blob& blob );
|
||||||
|
|
||||||
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _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_ LPCWSTR 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
|
// 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 );
|
_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 );
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
|
||||||
|
|
||||||
HRESULT __cdecl SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );
|
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
|
// 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,
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
|
||||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
_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,
|
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
|
||||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
||||||
|
|
||||||
@ -353,10 +351,10 @@ namespace DirectX
|
|||||||
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
|
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
|
||||||
|
|
||||||
HRESULT __cdecl SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
|
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 );
|
_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,
|
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 );
|
_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_
|
_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 = {};
|
TexMetadata mdata = {};
|
||||||
mdata.width = image.width;
|
mdata.width = image.width;
|
||||||
|
@ -22,31 +22,31 @@
|
|||||||
|
|
||||||
#include "bc.h"
|
#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 )
|
inline DWORD GetSRGBFlags(_In_ DWORD compress)
|
||||||
{
|
{
|
||||||
static_assert( TEX_COMPRESS_RGB_DITHER == BC_FLAGS_DITHER_RGB, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
|
static_assert(TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
|
||||||
static_assert( TEX_COMPRESS_A_DITHER == BC_FLAGS_DITHER_A, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
|
static_assert(TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
|
||||||
static_assert( TEX_COMPRESS_DITHER == (BC_FLAGS_DITHER_RGB | BC_FLAGS_DITHER_A), "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
|
static_assert(TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
|
||||||
static_assert( TEX_COMPRESS_UNIFORM == BC_FLAGS_UNIFORM, "TEX_COMPRESS_* flags should match BC_FLAGS_*" );
|
return (compress & TEX_COMPRESS_SRGB);
|
||||||
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 _GetSRGBFlags( _In_ DWORD compress )
|
inline bool DetermineEncoderSettings(_In_ DXGI_FORMAT format, _Out_ BC_ENCODE& pfEncode, _Out_ size_t& blocksize, _Out_ DWORD& cflags)
|
||||||
{
|
{
|
||||||
static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
|
switch (format)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_BC1_UNORM:
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
case DXGI_FORMAT_BC1_UNORM_SRGB: pfEncode = nullptr; blocksize = 8; cflags = 0; break;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
|
HRESULT CompressBC(
|
||||||
_In_ DWORD srgb, _In_ float alphaRef )
|
const Image& image,
|
||||||
{
|
const Image& result,
|
||||||
if ( !image.pixels || !result.pixels )
|
DWORD bcflags,
|
||||||
|
DWORD srgb,
|
||||||
|
float alphaRef)
|
||||||
|
{
|
||||||
|
if (!image.pixels || !result.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( image.width == result.width );
|
assert(image.width == result.width);
|
||||||
assert( image.height == result.height );
|
assert(image.height == result.height);
|
||||||
|
|
||||||
const DXGI_FORMAT format = image.format;
|
const DXGI_FORMAT format = image.format;
|
||||||
size_t sbpp = BitsPerPixel( format );
|
size_t sbpp = BitsPerPixel(format);
|
||||||
if ( !sbpp )
|
if (!sbpp)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( sbpp < 8 )
|
if (sbpp < 8)
|
||||||
{
|
{
|
||||||
// We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
|
// 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
|
// Round to bytes
|
||||||
sbpp = ( sbpp + 7 ) / 8;
|
sbpp = (sbpp + 7) / 8;
|
||||||
|
|
||||||
uint8_t *pDest = result.pixels;
|
uint8_t *pDest = result.pixels;
|
||||||
|
|
||||||
@ -99,124 +103,128 @@ static HRESULT _CompressBC( _In_ const Image& image, _In_ const Image& result, _
|
|||||||
BC_ENCODE pfEncode;
|
BC_ENCODE pfEncode;
|
||||||
size_t blocksize;
|
size_t blocksize;
|
||||||
DWORD cflags;
|
DWORD cflags;
|
||||||
if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
|
if (!DetermineEncoderSettings(result.format, pfEncode, blocksize, cflags))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
__declspec(align(16)) XMVECTOR temp[16];
|
__declspec(align(16)) XMVECTOR temp[16];
|
||||||
const uint8_t *pSrc = image.pixels;
|
const uint8_t *pSrc = image.pixels;
|
||||||
const uint8_t *pEnd = image.pixels + image.slicePitch;
|
const uint8_t *pEnd = image.pixels + image.slicePitch;
|
||||||
const size_t rowPitch = image.rowPitch;
|
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;
|
const uint8_t *sptr = pSrc;
|
||||||
uint8_t* dptr = pDest;
|
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;
|
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 );
|
size_t pw = std::min<size_t>(4, image.width - w);
|
||||||
assert( pw > 0 && ph > 0 );
|
assert(pw > 0 && ph > 0);
|
||||||
|
|
||||||
ptrdiff_t bytesLeft = pEnd - sptr;
|
ptrdiff_t bytesLeft = pEnd - sptr;
|
||||||
assert( bytesLeft > 0 );
|
assert(bytesLeft > 0);
|
||||||
size_t bytesToRead = std::min<size_t>( rowPitch, bytesLeft );
|
size_t bytesToRead = std::min<size_t>(rowPitch, bytesLeft);
|
||||||
if ( !_LoadScanline( &temp[0], pw, sptr, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[0], pw, sptr, bytesToRead, format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( ph > 1 )
|
if (ph > 1)
|
||||||
{
|
{
|
||||||
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch );
|
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch);
|
||||||
if ( !_LoadScanline( &temp[4], pw, sptr + rowPitch, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[4], pw, sptr + rowPitch, bytesToRead, format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( ph > 2 )
|
if (ph > 2)
|
||||||
{
|
{
|
||||||
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 2 );
|
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 2);
|
||||||
if ( !_LoadScanline( &temp[8], pw, sptr + rowPitch*2, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[8], pw, sptr + rowPitch * 2, bytesToRead, format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( ph > 3 )
|
if (ph > 3)
|
||||||
{
|
{
|
||||||
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 3 );
|
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 3);
|
||||||
if ( !_LoadScanline( &temp[12], pw, sptr + rowPitch*3, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[12], pw, sptr + rowPitch * 3, bytesToRead, format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pw != 4 || ph != 4 )
|
if (pw != 4 || ph != 4)
|
||||||
{
|
{
|
||||||
// Replicate pixels for partial block
|
// Replicate pixels for partial block
|
||||||
static const size_t uSrc[] = { 0, 0, 0, 1 };
|
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")
|
#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")
|
#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 )
|
if (pfEncode)
|
||||||
pfEncode( dptr, temp, bcflags );
|
pfEncode(dptr, temp, bcflags);
|
||||||
else
|
else
|
||||||
D3DXEncodeBC1( dptr, temp, alphaRef, bcflags );
|
D3DXEncodeBC1(dptr, temp, alphaRef, bcflags);
|
||||||
|
|
||||||
sptr += sbpp*4;
|
sptr += sbpp * 4;
|
||||||
dptr += blocksize;
|
dptr += blocksize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pSrc += rowPitch*4;
|
pSrc += rowPitch * 4;
|
||||||
pDest += result.rowPitch;
|
pDest += result.rowPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
static HRESULT _CompressBC_Parallel( _In_ const Image& image, _In_ const Image& result, _In_ DWORD bcflags,
|
HRESULT CompressBC_Parallel(
|
||||||
_In_ DWORD srgb, _In_ float alphaRef )
|
const Image& image,
|
||||||
{
|
const Image& result,
|
||||||
if ( !image.pixels || !result.pixels )
|
DWORD bcflags,
|
||||||
|
DWORD srgb,
|
||||||
|
float alphaRef)
|
||||||
|
{
|
||||||
|
if (!image.pixels || !result.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( image.width == result.width );
|
assert(image.width == result.width);
|
||||||
assert( image.height == result.height );
|
assert(image.height == result.height);
|
||||||
|
|
||||||
const DXGI_FORMAT format = image.format;
|
const DXGI_FORMAT format = image.format;
|
||||||
size_t sbpp = BitsPerPixel( format );
|
size_t sbpp = BitsPerPixel(format);
|
||||||
if ( !sbpp )
|
if (!sbpp)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( sbpp < 8 )
|
if (sbpp < 8)
|
||||||
{
|
{
|
||||||
// We don't support compressing from monochrome (DXGI_FORMAT_R1_UNORM)
|
// 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
|
// Round to bytes
|
||||||
sbpp = ( sbpp + 7 ) / 8;
|
sbpp = (sbpp + 7) / 8;
|
||||||
|
|
||||||
const uint8_t *pEnd = image.pixels + image.slicePitch;
|
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;
|
BC_ENCODE pfEncode;
|
||||||
size_t blocksize;
|
size_t blocksize;
|
||||||
DWORD cflags;
|
DWORD cflags;
|
||||||
if ( !_DetermineEncoderSettings( result.format, pfEncode, blocksize, cflags ) )
|
if (!DetermineEncoderSettings(result.format, pfEncode, blocksize, cflags))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
// Refactored version of loop to support parallel independance
|
// 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;
|
bool fail = false;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#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 y = nb / nbWidth;
|
||||||
int x = ( nb - (y*nbWidth) ) * 4;
|
int x = (nb - (y*nbWidth)) * 4;
|
||||||
y *= 4;
|
y *= 4;
|
||||||
|
|
||||||
assert( (x >= 0) && (x < int(image.width)) );
|
assert((x >= 0) && (x < int(image.width)));
|
||||||
assert( (y >= 0) && (y < int(image.height)) );
|
assert((y >= 0) && (y < int(image.height)));
|
||||||
|
|
||||||
size_t rowPitch = image.rowPitch;
|
size_t rowPitch = image.rowPitch;
|
||||||
const uint8_t *pSrc = image.pixels + (y*rowPitch) + (x*sbpp);
|
const uint8_t *pSrc = image.pixels + (y*rowPitch) + (x*sbpp);
|
||||||
|
|
||||||
uint8_t *pDest = result.pixels + (nb*blocksize);
|
uint8_t *pDest = result.pixels + (nb*blocksize);
|
||||||
|
|
||||||
size_t ph = std::min<size_t>( 4, image.height - y );
|
size_t ph = std::min<size_t>(4, image.height - y);
|
||||||
size_t pw = std::min<size_t>( 4, image.width - x );
|
size_t pw = std::min<size_t>(4, image.width - x);
|
||||||
assert( pw > 0 && ph > 0 );
|
assert(pw > 0 && ph > 0);
|
||||||
|
|
||||||
ptrdiff_t bytesLeft = pEnd - pSrc;
|
ptrdiff_t bytesLeft = pEnd - pSrc;
|
||||||
assert( bytesLeft > 0 );
|
assert(bytesLeft > 0);
|
||||||
size_t bytesToRead = std::min<size_t>( rowPitch, bytesLeft );
|
size_t bytesToRead = std::min<size_t>(rowPitch, bytesLeft);
|
||||||
|
|
||||||
__declspec(align(16)) XMVECTOR temp[16];
|
__declspec(align(16)) XMVECTOR temp[16];
|
||||||
if ( !_LoadScanline( &temp[0], pw, pSrc, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[0], pw, pSrc, bytesToRead, format))
|
||||||
fail = true;
|
fail = true;
|
||||||
|
|
||||||
if ( ph > 1 )
|
if (ph > 1)
|
||||||
{
|
{
|
||||||
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch );
|
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch);
|
||||||
if ( !_LoadScanline( &temp[4], pw, pSrc + rowPitch, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[4], pw, pSrc + rowPitch, bytesToRead, format))
|
||||||
fail = true;
|
fail = true;
|
||||||
|
|
||||||
if ( ph > 2 )
|
if (ph > 2)
|
||||||
{
|
{
|
||||||
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 2 );
|
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 2);
|
||||||
if ( !_LoadScanline( &temp[8], pw, pSrc + rowPitch*2, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[8], pw, pSrc + rowPitch * 2, bytesToRead, format))
|
||||||
fail = true;
|
fail = true;
|
||||||
|
|
||||||
if ( ph > 3 )
|
if (ph > 3)
|
||||||
{
|
{
|
||||||
bytesToRead = std::min<size_t>( rowPitch, bytesLeft - rowPitch * 3 );
|
bytesToRead = std::min<size_t>(rowPitch, bytesLeft - rowPitch * 3);
|
||||||
if ( !_LoadScanline( &temp[12], pw, pSrc + rowPitch*3, bytesToRead, format ) )
|
if (!_LoadScanline(&temp[12], pw, pSrc + rowPitch * 3, bytesToRead, format))
|
||||||
fail = true;
|
fail = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pw != 4 || ph != 4 )
|
if (pw != 4 || ph != 4)
|
||||||
{
|
{
|
||||||
// Replicate pixels for partial block
|
// Replicate pixels for partial block
|
||||||
static const size_t uSrc[] = { 0, 0, 0, 1 };
|
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 )
|
if (pfEncode)
|
||||||
pfEncode( pDest, temp, bcflags );
|
pfEncode(pDest, temp, bcflags);
|
||||||
else
|
else
|
||||||
D3DXEncodeBC1( pDest, temp, alphaRef, bcflags );
|
D3DXEncodeBC1(pDest, temp, alphaRef, bcflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (fail) ? E_FAIL : S_OK;
|
return (fail) ? E_FAIL : S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _OPENMP
|
#endif // _OPENMP
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static DXGI_FORMAT _DefaultDecompress( _In_ DXGI_FORMAT format )
|
DXGI_FORMAT DefaultDecompress(_In_ DXGI_FORMAT format)
|
||||||
{
|
{
|
||||||
switch( format )
|
switch (format)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_BC1_TYPELESS:
|
case DXGI_FORMAT_BC1_TYPELESS:
|
||||||
case DXGI_FORMAT_BC1_UNORM:
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
@ -369,39 +376,39 @@ static DXGI_FORMAT _DefaultDecompress( _In_ DXGI_FORMAT format )
|
|||||||
default:
|
default:
|
||||||
return DXGI_FORMAT_UNKNOWN;
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result )
|
HRESULT DecompressBC(_In_ const Image& cImage, _In_ const Image& result)
|
||||||
{
|
{
|
||||||
if ( !cImage.pixels || !result.pixels )
|
if (!cImage.pixels || !result.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( cImage.width == result.width );
|
assert(cImage.width == result.width);
|
||||||
assert( cImage.height == result.height );
|
assert(cImage.height == result.height);
|
||||||
|
|
||||||
const DXGI_FORMAT format = result.format;
|
const DXGI_FORMAT format = result.format;
|
||||||
size_t dbpp = BitsPerPixel( format );
|
size_t dbpp = BitsPerPixel(format);
|
||||||
if ( !dbpp )
|
if (!dbpp)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( dbpp < 8 )
|
if (dbpp < 8)
|
||||||
{
|
{
|
||||||
// We don't support decompressing to monochrome (DXGI_FORMAT_R1_UNORM)
|
// 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
|
// Round to bytes
|
||||||
dbpp = ( dbpp + 7 ) / 8;
|
dbpp = (dbpp + 7) / 8;
|
||||||
|
|
||||||
uint8_t *pDest = result.pixels;
|
uint8_t *pDest = result.pixels;
|
||||||
if ( !pDest )
|
if (!pDest)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
// Promote "typeless" BC formats
|
// Promote "typeless" BC formats
|
||||||
DXGI_FORMAT cformat;
|
DXGI_FORMAT cformat;
|
||||||
switch( cImage.format )
|
switch (cImage.format)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
|
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
|
||||||
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_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
|
// Determine BC format decoder
|
||||||
BC_DECODE pfDecode;
|
BC_DECODE pfDecode;
|
||||||
size_t sbpp;
|
size_t sbpp;
|
||||||
switch(cformat)
|
switch (cformat)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_BC1_UNORM:
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
|
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:
|
||||||
case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
|
case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
|
||||||
default:
|
default:
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
__declspec(align(16)) XMVECTOR temp[16];
|
__declspec(align(16)) XMVECTOR temp[16];
|
||||||
const uint8_t *pSrc = cImage.pixels;
|
const uint8_t *pSrc = cImage.pixels;
|
||||||
const size_t rowPitch = result.rowPitch;
|
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;
|
const uint8_t *sptr = pSrc;
|
||||||
uint8_t* dptr = pDest;
|
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;
|
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 );
|
pfDecode(temp, sptr);
|
||||||
_ConvertScanline( temp, 16, format, cformat, 0 );
|
_ConvertScanline(temp, 16, format, cformat, 0);
|
||||||
|
|
||||||
size_t pw = std::min<size_t>( 4, cImage.width - w );
|
size_t pw = std::min<size_t>(4, cImage.width - w);
|
||||||
assert( pw > 0 && ph > 0 );
|
assert(pw > 0 && ph > 0);
|
||||||
|
|
||||||
if ( !_StoreScanline( dptr, rowPitch, format, &temp[0], pw ) )
|
if (!_StoreScanline(dptr, rowPitch, format, &temp[0], pw))
|
||||||
return E_FAIL;
|
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;
|
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;
|
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;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sptr += sbpp;
|
sptr += sbpp;
|
||||||
dptr += dbpp*4;
|
dptr += dbpp * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
pSrc += cImage.rowPitch;
|
pSrc += cImage.rowPitch;
|
||||||
pDest += rowPitch*4;
|
pDest += rowPitch * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
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;
|
return false;
|
||||||
|
|
||||||
// Promote "typeless" BC formats
|
// Promote "typeless" BC formats
|
||||||
DXGI_FORMAT cformat;
|
DXGI_FORMAT cformat;
|
||||||
switch( cImage.format )
|
switch (cImage.format)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
|
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
|
||||||
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_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
|
// Determine BC format decoder
|
||||||
BC_DECODE pfDecode;
|
BC_DECODE pfDecode;
|
||||||
size_t sbpp;
|
size_t sbpp;
|
||||||
switch(cformat)
|
switch (cformat)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_BC1_UNORM:
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
|
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];
|
__declspec(align(16)) XMVECTOR temp[16];
|
||||||
const uint8_t *pPixels = cImage.pixels;
|
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;
|
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;
|
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 );
|
size_t pw = std::min<size_t>(4, cImage.width - w);
|
||||||
assert( pw > 0 && ph > 0 );
|
assert(pw > 0 && ph > 0);
|
||||||
|
|
||||||
if ( pw == 4 && ph == 4 )
|
if (pw == 4 && ph == 4)
|
||||||
{
|
{
|
||||||
// Full blocks
|
// Full blocks
|
||||||
for( size_t j = 0; j < 16; ++j )
|
for (size_t j = 0; j < 16; ++j)
|
||||||
{
|
{
|
||||||
XMVECTOR alpha = XMVectorSplatW( temp[j] );
|
XMVECTOR alpha = XMVectorSplatW(temp[j]);
|
||||||
if ( XMVector4Less( alpha, threshold ) )
|
if (XMVector4Less(alpha, threshold))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Handle partial blocks
|
// 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 ] );
|
XMVECTOR alpha = XMVectorSplatW(temp[y * 4 + x]);
|
||||||
if ( XMVector4Less( alpha, threshold ) )
|
if (XMVector4Less(alpha, threshold))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -569,7 +578,8 @@ bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
@ -580,22 +590,27 @@ bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
|
|||||||
// Compression
|
// Compression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsTypeless(format)
|
if (IsTypeless(format)
|
||||||
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
|
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
// Create compressed image
|
// Create compressed image
|
||||||
HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
|
HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *img = image.GetImage( 0, 0, 0 );
|
const Image *img = image.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
@ -607,76 +622,82 @@ HRESULT Compress( const Image& srcImage, DXGI_FORMAT format, DWORD compress, flo
|
|||||||
#ifndef _OPENMP
|
#ifndef _OPENMP
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
#else
|
#else
|
||||||
hr = _CompressBC_Parallel( srcImage, *img, _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
|
hr = CompressBC_Parallel(srcImage, *img, GetBCFlags(compress), GetSRGBFlags(compress), alphaRef);
|
||||||
#endif // _OPENMP
|
#endif // _OPENMP
|
||||||
}
|
}
|
||||||
else
|
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();
|
image.Release();
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
|
HRESULT DirectX::Compress(
|
||||||
DXGI_FORMAT format, DWORD compress, float alphaRef, ScratchImage& cImages )
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsCompressed(metadata.format) || !IsCompressed(format) )
|
if (IsCompressed(metadata.format) || !IsCompressed(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsTypeless(format)
|
if (IsTypeless(format)
|
||||||
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
|
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
|
|
||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
mdata2.format = format;
|
mdata2.format = format;
|
||||||
HRESULT hr = cImages.Initialize( mdata2 );
|
HRESULT hr = cImages.Initialize(mdata2);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if ( nimages != cImages.GetImageCount() )
|
if (nimages != cImages.GetImageCount())
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Image* dest = cImages.GetImages();
|
const Image* dest = cImages.GetImages();
|
||||||
if ( !dest )
|
if (!dest)
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return E_POINTER;
|
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();
|
cImages.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (compress & TEX_COMPRESS_PARALLEL) )
|
if ((compress & TEX_COMPRESS_PARALLEL))
|
||||||
{
|
{
|
||||||
#ifndef _OPENMP
|
#ifndef _OPENMP
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
#else
|
#else
|
||||||
if ( compress & TEX_COMPRESS_PARALLEL )
|
if (compress & TEX_COMPRESS_PARALLEL)
|
||||||
{
|
{
|
||||||
hr = _CompressBC_Parallel( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
|
hr = CompressBC_Parallel(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), alphaRef);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -686,8 +707,8 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hr = _CompressBC( src, dest[ index ], _GetBCFlags( compress ), _GetSRGBFlags( compress ), alphaRef );
|
hr = CompressBC(src, dest[index], GetBCFlags(compress), GetSRGBFlags(compress), alphaRef);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -703,16 +724,19 @@ HRESULT Compress( const Image* srcImages, size_t nimages, const TexMetadata& met
|
|||||||
// Decompression
|
// Decompression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( format == DXGI_FORMAT_UNKNOWN )
|
if (format == DXGI_FORMAT_UNKNOWN)
|
||||||
{
|
{
|
||||||
// Pick a default decompressed format based on BC input format
|
// Pick a default decompressed format based on BC input format
|
||||||
format = _DefaultDecompress( cImage.format );
|
format = DefaultDecompress(cImage.format);
|
||||||
if ( format == DXGI_FORMAT_UNKNOWN )
|
if (format == DXGI_FORMAT_UNKNOWN)
|
||||||
{
|
{
|
||||||
// Input is not a compressed format
|
// Input is not a compressed format
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -720,48 +744,52 @@ HRESULT Decompress( const Image& cImage, DXGI_FORMAT format, ScratchImage& image
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( !IsValid(format) )
|
if (!IsValid(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
|
if (IsTypeless(format) || IsPlanar(format) || IsPalettized(format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create decompressed image
|
// Create decompressed image
|
||||||
HRESULT hr = image.Initialize2D( format, cImage.width, cImage.height, 1, 1 );
|
HRESULT hr = image.Initialize2D(format, cImage.width, cImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *img = image.GetImage( 0, 0, 0 );
|
const Image *img = image.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress single image
|
// Decompress single image
|
||||||
hr = _DecompressBC( cImage, *img );
|
hr = DecompressBC(cImage, *img);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
image.Release();
|
image.Release();
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& metadata,
|
HRESULT DirectX::Decompress(
|
||||||
DXGI_FORMAT format, ScratchImage& images )
|
const Image* cImages,
|
||||||
|
size_t nimages,
|
||||||
|
const TexMetadata& metadata,
|
||||||
|
DXGI_FORMAT format,
|
||||||
|
ScratchImage& images)
|
||||||
{
|
{
|
||||||
if ( !cImages || !nimages )
|
if (!cImages || !nimages)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( !IsCompressed(metadata.format) || IsCompressed(format) )
|
if (!IsCompressed(metadata.format) || IsCompressed(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( format == DXGI_FORMAT_UNKNOWN )
|
if (format == DXGI_FORMAT_UNKNOWN)
|
||||||
{
|
{
|
||||||
// Pick a default decompressed format based on BC input format
|
// Pick a default decompressed format based on BC input format
|
||||||
format = _DefaultDecompress( cImages[0].format );
|
format = DefaultDecompress(cImages[0].format);
|
||||||
if ( format == DXGI_FORMAT_UNKNOWN )
|
if (format == DXGI_FORMAT_UNKNOWN)
|
||||||
{
|
{
|
||||||
// Input is not a compressed format
|
// Input is not a compressed format
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -769,53 +797,53 @@ HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& met
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( !IsValid(format) )
|
if (!IsValid(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsTypeless(format) || IsPlanar(format) || IsPalettized(format) )
|
if (IsTypeless(format) || IsPlanar(format) || IsPalettized(format))
|
||||||
HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
images.Release();
|
images.Release();
|
||||||
|
|
||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
mdata2.format = format;
|
mdata2.format = format;
|
||||||
HRESULT hr = images.Initialize( mdata2 );
|
HRESULT hr = images.Initialize(mdata2);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if ( nimages != images.GetImageCount() )
|
if (nimages != images.GetImageCount())
|
||||||
{
|
{
|
||||||
images.Release();
|
images.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Image* dest = images.GetImages();
|
const Image* dest = images.GetImages();
|
||||||
if ( !dest )
|
if (!dest)
|
||||||
{
|
{
|
||||||
images.Release();
|
images.Release();
|
||||||
return E_POINTER;
|
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 ];
|
const Image& src = cImages[index];
|
||||||
if ( !IsCompressed( src.format ) )
|
if (!IsCompressed(src.format))
|
||||||
{
|
{
|
||||||
images.Release();
|
images.Release();
|
||||||
return E_FAIL;
|
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();
|
images.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _DecompressBC( src, dest[ index ] );
|
hr = DecompressBC(src, dest[index]);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
images.Release();
|
images.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -824,5 +852,3 @@ HRESULT Decompress( const Image* cImages, size_t nimages, const TexMetadata& met
|
|||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
|
||||||
|
@ -17,65 +17,70 @@
|
|||||||
|
|
||||||
#include "bcdirectcompute.h"
|
#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*" );
|
inline DWORD GetSRGBFlags(_In_ DWORD compress)
|
||||||
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*" );
|
static_assert(TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
|
||||||
return ( compress & TEX_COMPRESS_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
|
// 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 )
|
HRESULT ConvertToRGBA32(
|
||||||
{
|
const Image& srcImage,
|
||||||
if ( !srcImage.pixels )
|
ScratchImage& image,
|
||||||
|
bool srgb,
|
||||||
|
DWORD filter)
|
||||||
|
{
|
||||||
|
if (!srcImage.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
|
DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
|
||||||
HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
|
HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *img = image.GetImage( 0, 0, 0 );
|
const Image *img = image.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* pDest = img->pixels;
|
uint8_t* pDest = img->pixels;
|
||||||
if ( !pDest )
|
if (!pDest)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( ( sizeof(XMVECTOR) * srcImage.width ), 16 ) ) );
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR) * srcImage.width), 16)));
|
||||||
if ( !scanline )
|
if (!scanline)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *pSrc = srcImage.pixels;
|
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();
|
image.Release();
|
||||||
return E_FAIL;
|
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();
|
image.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -86,70 +91,77 @@ static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage&
|
|||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
|
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image, _In_ DWORD filter )
|
HRESULT ConvertToRGBAF32(
|
||||||
{
|
const Image& srcImage,
|
||||||
if ( !srcImage.pixels )
|
ScratchImage& image,
|
||||||
|
DWORD filter)
|
||||||
|
{
|
||||||
|
if (!srcImage.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
|
HRESULT hr = image.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *img = image.GetImage( 0, 0, 0 );
|
const Image *img = image.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* pDest = img->pixels;
|
uint8_t* pDest = img->pixels;
|
||||||
if ( !pDest )
|
if (!pDest)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t *pSrc = srcImage.pixels;
|
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();
|
image.Release();
|
||||||
return E_FAIL;
|
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;
|
pSrc += srcImage.rowPitch;
|
||||||
pDest += img->rowPitch;
|
pDest += img->rowPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Compress using GPU, converting to the proper input format for the shader if needed
|
// 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 )
|
inline HRESULT GPUCompress(
|
||||||
{
|
_In_ GPUCompressBC* gpubc,
|
||||||
if ( !gpubc )
|
const Image& srcImage,
|
||||||
|
const Image& destImage,
|
||||||
|
DWORD compress)
|
||||||
|
{
|
||||||
|
if (!gpubc)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( srcImage.pixels && destImage.pixels );
|
assert(srcImage.pixels && destImage.pixels);
|
||||||
|
|
||||||
DXGI_FORMAT format = gpubc->GetSourceFormat();
|
DXGI_FORMAT format = gpubc->GetSourceFormat();
|
||||||
|
|
||||||
if ( srcImage.format == format )
|
if (srcImage.format == format)
|
||||||
{
|
{
|
||||||
// Input is already in our required source format
|
// Input is already in our required source format
|
||||||
return gpubc->Compress( srcImage, destImage );
|
return gpubc->Compress(srcImage, destImage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -157,20 +169,20 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
|
|||||||
ScratchImage image;
|
ScratchImage image;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
DWORD srgb = _GetSRGBFlags( compress );
|
DWORD srgb = GetSRGBFlags(compress);
|
||||||
|
|
||||||
switch( format )
|
switch (format)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
hr = _ConvertToRGBA32( srcImage, image, false, srgb );
|
hr = ConvertToRGBA32(srcImage, image, false, srgb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||||
hr = _ConvertToRGBA32( srcImage, image, true, srgb );
|
hr = ConvertToRGBA32(srcImage, image, true, srgb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||||
hr = _ConvertToRGBAF32( srcImage, image, srgb );
|
hr = ConvertToRGBAF32(srcImage, image, srgb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -178,17 +190,17 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *img = image.GetImage( 0, 0, 0 );
|
const Image *img = image.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
return gpubc->Compress( *img, destImage );
|
return gpubc->Compress(*img, destImage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
// Entry-points
|
// Entry-points
|
||||||
@ -198,94 +210,107 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
|
|||||||
// Compression
|
// Compression
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsTypeless(format)
|
if (IsTypeless(format)
|
||||||
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
|
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
// Setup GPU compressor
|
// Setup GPU compressor
|
||||||
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
|
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
|
||||||
if ( !gpubc )
|
if (!gpubc)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
HRESULT hr = gpubc->Initialize( pDevice );
|
HRESULT hr = gpubc->Initialize(pDevice);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = gpubc->Prepare( srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
|
hr = gpubc->Prepare(srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Create workspace for result
|
// Create workspace for result
|
||||||
hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
|
hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *img = image.GetImage( 0, 0, 0 );
|
const Image *img = image.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _GPUCompress( gpubc.get(), srcImage, *img, compress );
|
hr = GPUCompress(gpubc.get(), srcImage, *img, compress);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
image.Release();
|
image.Release();
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
|
HRESULT DirectX::Compress(
|
||||||
DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& cImages )
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsCompressed(metadata.format) || !IsCompressed(format) )
|
if (IsCompressed(metadata.format) || !IsCompressed(format))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsTypeless(format)
|
if (IsTypeless(format)
|
||||||
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
|
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
|
|
||||||
// Setup GPU compressor
|
// Setup GPU compressor
|
||||||
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
|
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
|
||||||
if ( !gpubc )
|
if (!gpubc)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
HRESULT hr = gpubc->Initialize( pDevice );
|
HRESULT hr = gpubc->Initialize(pDevice);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Create workspace for result
|
// Create workspace for result
|
||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
mdata2.format = format;
|
mdata2.format = format;
|
||||||
hr = cImages.Initialize( mdata2 );
|
hr = cImages.Initialize(mdata2);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if ( nimages != cImages.GetImageCount() )
|
if (nimages != cImages.GetImageCount())
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Image* dest = cImages.GetImages();
|
const Image* dest = cImages.GetImages();
|
||||||
if ( !dest )
|
if (!dest)
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process images (ordered by size)
|
// Process images (ordered by size)
|
||||||
switch( metadata.dimension )
|
switch (metadata.dimension)
|
||||||
{
|
{
|
||||||
case TEX_DIMENSION_TEXTURE1D:
|
case TEX_DIMENSION_TEXTURE1D:
|
||||||
case TEX_DIMENSION_TEXTURE2D:
|
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 w = metadata.width;
|
||||||
size_t h = metadata.height;
|
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) );
|
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
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 );
|
size_t index = metadata.ComputeIndex(level, item, 0);
|
||||||
if ( index >= nimages )
|
if (index >= nimages)
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return E_FAIL;
|
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();
|
cImages.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
|
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( h > 1 )
|
if (h > 1)
|
||||||
h >>= 1;
|
h >>= 1;
|
||||||
|
|
||||||
if ( w > 1 )
|
if (w > 1)
|
||||||
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 h = metadata.height;
|
||||||
size_t d = metadata.depth;
|
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) );
|
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
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 );
|
size_t index = metadata.ComputeIndex(level, 0, slice);
|
||||||
if ( index >= nimages )
|
if (index >= nimages)
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return E_FAIL;
|
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();
|
cImages.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
|
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
cImages.Release();
|
cImages.Release();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( h > 1 )
|
if (h > 1)
|
||||||
h >>= 1;
|
h >>= 1;
|
||||||
|
|
||||||
if ( w > 1 )
|
if (w > 1)
|
||||||
w >>= 1;
|
w >>= 1;
|
||||||
|
|
||||||
if ( d > 1 )
|
if (d > 1)
|
||||||
d >>= 1;
|
d >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
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"
|
#include "directxtexp.h"
|
||||||
|
|
||||||
|
using namespace DirectX;
|
||||||
using Microsoft::WRL::ComPtr;
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
namespace DirectX
|
namespace
|
||||||
{
|
{
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
//-------------------------------------------------------------------------------------
|
// Do flip/rotate operation using WIC
|
||||||
// Do flip/rotate operation using WIC
|
//-------------------------------------------------------------------------------------
|
||||||
//-------------------------------------------------------------------------------------
|
HRESULT PerformFlipRotateUsingWIC(
|
||||||
static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWORD flags,
|
const Image& srcImage,
|
||||||
_In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
|
DWORD flags,
|
||||||
{
|
const WICPixelFormatGUID& pfGUID,
|
||||||
if ( !srcImage.pixels || !destImage.pixels )
|
const Image& destImage)
|
||||||
|
{
|
||||||
|
if (!srcImage.pixels || !destImage.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( srcImage.format == destImage.format );
|
assert(srcImage.format == destImage.format);
|
||||||
|
|
||||||
bool iswic2 = false;
|
bool iswic2 = false;
|
||||||
IWICImagingFactory* pWIC = GetWICFactory(iswic2);
|
IWICImagingFactory* pWIC = GetWICFactory(iswic2);
|
||||||
if ( !pWIC )
|
if (!pWIC)
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
ComPtr<IWICBitmap> source;
|
ComPtr<IWICBitmap> source;
|
||||||
HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
|
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 ),
|
static_cast<UINT>(srcImage.rowPitch), static_cast<UINT>(srcImage.slicePitch),
|
||||||
srcImage.pixels, source.GetAddressOf() );
|
srcImage.pixels, source.GetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
ComPtr<IWICBitmapFlipRotator> FR;
|
ComPtr<IWICBitmapFlipRotator> FR;
|
||||||
hr = pWIC->CreateBitmapFlipRotator( FR.GetAddressOf() );
|
hr = pWIC->CreateBitmapFlipRotator(FR.GetAddressOf());
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) );
|
hr = FR->Initialize(source.Get(), static_cast<WICBitmapTransformOptions>(flags));
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
WICPixelFormatGUID pfFR;
|
WICPixelFormatGUID pfFR;
|
||||||
hr = FR->GetPixelFormat( &pfFR );
|
hr = FR->GetPixelFormat(&pfFR);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return 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...
|
// 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;
|
UINT nwidth, nheight;
|
||||||
hr = FR->GetSize( &nwidth, &nheight );
|
hr = FR->GetSize(&nwidth, &nheight);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if ( destImage.width != nwidth || destImage.height != nheight )
|
if (destImage.width != nwidth || destImage.height != nheight)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
|
hr = FR->CopyPixels(0, static_cast<UINT>(destImage.rowPitch), static_cast<UINT>(destImage.slicePitch), destImage.pixels);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Do conversion, flip/rotate using WIC, conversion cycle
|
// Do conversion, flip/rotate using WIC, conversion cycle
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
|
HRESULT PerformFlipRotateViaF32(
|
||||||
{
|
const Image& srcImage,
|
||||||
if ( !srcImage.pixels || !destImage.pixels )
|
DWORD flags,
|
||||||
|
const Image& destImage)
|
||||||
|
{
|
||||||
|
if (!srcImage.pixels || !destImage.pixels)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
|
assert(srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT);
|
||||||
assert( srcImage.format == destImage.format );
|
assert(srcImage.format == destImage.format);
|
||||||
|
|
||||||
ScratchImage temp;
|
ScratchImage temp;
|
||||||
HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
|
HRESULT hr = _ConvertToR32G32B32A32(srcImage, temp);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *tsrc = temp.GetImage( 0, 0, 0 );
|
const Image *tsrc = temp.GetImage(0, 0, 0);
|
||||||
if ( !tsrc )
|
if (!tsrc)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
ScratchImage rtemp;
|
ScratchImage rtemp;
|
||||||
hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
|
hr = rtemp.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *tdest = rtemp.GetImage( 0, 0, 0 );
|
const Image *tdest = rtemp.GetImage(0, 0, 0);
|
||||||
if ( !tdest )
|
if (!tdest)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
|
hr = PerformFlipRotateUsingWIC(*tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
temp.Release();
|
temp.Release();
|
||||||
|
|
||||||
hr = _ConvertFromR32G32B32A32( *tdest, destImage );
|
hr = _ConvertFromR32G32B32A32(*tdest, destImage);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -130,32 +137,35 @@ static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD
|
|||||||
// Flip/rotate image
|
// Flip/rotate image
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_POINTER;
|
||||||
|
|
||||||
if ( !flags )
|
if (!flags)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( (srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX) )
|
if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsCompressed( srcImage.format ) )
|
if (IsCompressed(srcImage.format))
|
||||||
{
|
{
|
||||||
// We don't support flip/rotate operations on compressed images
|
// 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_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_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_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_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_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_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
|
// 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 0:
|
||||||
case TEX_FR_ROTATE90:
|
case TEX_FR_ROTATE90:
|
||||||
@ -170,33 +180,33 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
|
|||||||
size_t nwidth = srcImage.width;
|
size_t nwidth = srcImage.width;
|
||||||
size_t nheight = srcImage.height;
|
size_t nheight = srcImage.height;
|
||||||
|
|
||||||
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
|
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
|
||||||
{
|
{
|
||||||
nwidth = srcImage.height;
|
nwidth = srcImage.height;
|
||||||
nheight = srcImage.width;
|
nheight = srcImage.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 );
|
HRESULT hr = image.Initialize2D(srcImage.format, nwidth, nheight, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *rimage = image.GetImage( 0, 0, 0 );
|
const Image *rimage = image.GetImage(0, 0, 0);
|
||||||
if ( !rimage )
|
if (!rimage)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
WICPixelFormatGUID pfGUID;
|
WICPixelFormatGUID pfGUID;
|
||||||
if ( _DXGIToWIC( srcImage.format, pfGUID ) )
|
if (_DXGIToWIC(srcImage.format, pfGUID))
|
||||||
{
|
{
|
||||||
// Case 1: Source format is supported by Windows Imaging Component
|
// Case 1: Source format is supported by Windows Imaging Component
|
||||||
hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage );
|
hr = PerformFlipRotateUsingWIC(srcImage, flags, pfGUID, *rimage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
|
// 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();
|
image.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -210,27 +220,31 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
|
|||||||
// Flip/rotate image (complex)
|
// Flip/rotate image (complex)
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
|
HRESULT DirectX::FlipRotate(
|
||||||
DWORD flags, ScratchImage& result )
|
const Image* srcImages,
|
||||||
|
size_t nimages,
|
||||||
|
const TexMetadata& metadata,
|
||||||
|
DWORD flags,
|
||||||
|
ScratchImage& result)
|
||||||
{
|
{
|
||||||
if ( !srcImages || !nimages )
|
if (!srcImages || !nimages)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsCompressed( metadata.format ) )
|
if (IsCompressed(metadata.format))
|
||||||
{
|
{
|
||||||
// We don't support flip/rotate operations on compressed images
|
// 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_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_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_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_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_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_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
|
// 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 0:
|
||||||
case TEX_FR_ROTATE90:
|
case TEX_FR_ROTATE90:
|
||||||
@ -245,51 +259,51 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
|||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
|
|
||||||
bool flipwh = false;
|
bool flipwh = false;
|
||||||
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
|
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
|
||||||
{
|
{
|
||||||
flipwh = true;
|
flipwh = true;
|
||||||
mdata2.width = metadata.height;
|
mdata2.width = metadata.height;
|
||||||
mdata2.height = metadata.width;
|
mdata2.height = metadata.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = result.Initialize( mdata2 );
|
HRESULT hr = result.Initialize(mdata2);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if ( nimages != result.GetImageCount() )
|
if (nimages != result.GetImageCount())
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Image* dest = result.GetImages();
|
const Image* dest = result.GetImages();
|
||||||
if ( !dest )
|
if (!dest)
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
WICPixelFormatGUID pfGUID;
|
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 ];
|
const Image& src = srcImages[index];
|
||||||
if ( src.format != metadata.format )
|
if (src.format != metadata.format)
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
|
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
const Image& dst = dest[ index ];
|
const Image& dst = dest[index];
|
||||||
assert( dst.format == metadata.format );
|
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();
|
result.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -297,7 +311,7 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( src.width != dst.width || src.height != dst.height )
|
if (src.width != dst.width || src.height != dst.height)
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -307,15 +321,15 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
|||||||
if (wicpf)
|
if (wicpf)
|
||||||
{
|
{
|
||||||
// Case 1: Source format is supported by Windows Imaging Component
|
// Case 1: Source format is supported by Windows Imaging Component
|
||||||
hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst );
|
hr = PerformFlipRotateUsingWIC(src, flags, pfGUID, dst);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
|
// 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();
|
result.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -324,5 +338,3 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
|||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
|
||||||
|
@ -17,46 +17,51 @@
|
|||||||
|
|
||||||
namespace DirectX
|
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 );
|
using namespace DirectX;
|
||||||
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 );
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Determines number of image array entries and pixel size
|
// Determines number of image array entries and pixel size
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
|
void DirectX::_DetermineImageArray(
|
||||||
size_t& nImages, size_t& pixelSize )
|
const TexMetadata& metadata,
|
||||||
|
DWORD cpFlags,
|
||||||
|
size_t& nImages,
|
||||||
|
size_t& pixelSize)
|
||||||
{
|
{
|
||||||
assert( metadata.width > 0 && metadata.height > 0 && metadata.depth > 0 );
|
assert(metadata.width > 0 && metadata.height > 0 && metadata.depth > 0);
|
||||||
assert( metadata.arraySize > 0 );
|
assert(metadata.arraySize > 0);
|
||||||
assert( metadata.mipLevels > 0 );
|
assert(metadata.mipLevels > 0);
|
||||||
|
|
||||||
size_t _pixelSize = 0;
|
size_t _pixelSize = 0;
|
||||||
size_t _nimages = 0;
|
size_t _nimages = 0;
|
||||||
|
|
||||||
switch( metadata.dimension )
|
switch (metadata.dimension)
|
||||||
{
|
{
|
||||||
case TEX_DIMENSION_TEXTURE1D:
|
case TEX_DIMENSION_TEXTURE1D:
|
||||||
case TEX_DIMENSION_TEXTURE2D:
|
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 w = metadata.width;
|
||||||
size_t h = metadata.height;
|
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;
|
size_t rowPitch, slicePitch;
|
||||||
ComputePitch( metadata.format, w, h, rowPitch, slicePitch, cpFlags );
|
ComputePitch(metadata.format, w, h, rowPitch, slicePitch, cpFlags);
|
||||||
|
|
||||||
_pixelSize += slicePitch;
|
_pixelSize += slicePitch;
|
||||||
++_nimages;
|
++_nimages;
|
||||||
|
|
||||||
if ( h > 1 )
|
if (h > 1)
|
||||||
h >>= 1;
|
h >>= 1;
|
||||||
|
|
||||||
if ( w > 1 )
|
if (w > 1)
|
||||||
w >>= 1;
|
w >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,31 +73,31 @@ void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
|
|||||||
size_t h = metadata.height;
|
size_t h = metadata.height;
|
||||||
size_t d = metadata.depth;
|
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;
|
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;
|
_pixelSize += slicePitch;
|
||||||
++_nimages;
|
++_nimages;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( h > 1 )
|
if (h > 1)
|
||||||
h >>= 1;
|
h >>= 1;
|
||||||
|
|
||||||
if ( w > 1 )
|
if (w > 1)
|
||||||
w >>= 1;
|
w >>= 1;
|
||||||
|
|
||||||
if ( d > 1 )
|
if (d > 1)
|
||||||
d >>= 1;
|
d >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert( false );
|
assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,22 +110,26 @@ void _DetermineImageArray( const TexMetadata& metadata, DWORD cpFlags,
|
|||||||
// Fills in the image array entries
|
// Fills in the image array entries
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
|
bool DirectX::_SetupImageArray(
|
||||||
const TexMetadata& metadata, DWORD cpFlags,
|
uint8_t *pMemory,
|
||||||
Image* images, size_t nImages )
|
size_t pixelSize,
|
||||||
|
const TexMetadata& metadata,
|
||||||
|
DWORD cpFlags,
|
||||||
|
Image* images,
|
||||||
|
size_t nImages)
|
||||||
{
|
{
|
||||||
assert( pMemory );
|
assert(pMemory);
|
||||||
assert( pixelSize > 0 );
|
assert(pixelSize > 0);
|
||||||
assert( nImages > 0 );
|
assert(nImages > 0);
|
||||||
|
|
||||||
if ( !images )
|
if (!images)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
uint8_t* pixels = pMemory;
|
uint8_t* pixels = pMemory;
|
||||||
const uint8_t* pEndBits = pMemory + pixelSize;
|
const uint8_t* pEndBits = pMemory + pixelSize;
|
||||||
|
|
||||||
switch( metadata.dimension )
|
switch (metadata.dimension)
|
||||||
{
|
{
|
||||||
case TEX_DIMENSION_TEXTURE1D:
|
case TEX_DIMENSION_TEXTURE1D:
|
||||||
case TEX_DIMENSION_TEXTURE2D:
|
case TEX_DIMENSION_TEXTURE2D:
|
||||||
@ -129,20 +138,20 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
|
|||||||
return false;
|
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 w = metadata.width;
|
||||||
size_t h = metadata.height;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t rowPitch, slicePitch;
|
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].width = w;
|
||||||
images[index].height = h;
|
images[index].height = h;
|
||||||
@ -153,15 +162,15 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
|
|||||||
++index;
|
++index;
|
||||||
|
|
||||||
pixels += slicePitch;
|
pixels += slicePitch;
|
||||||
if ( pixels > pEndBits )
|
if (pixels > pEndBits)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( h > 1 )
|
if (h > 1)
|
||||||
h >>= 1;
|
h >>= 1;
|
||||||
|
|
||||||
if ( w > 1 )
|
if (w > 1)
|
||||||
w >>= 1;
|
w >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,14 +187,14 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
|
|||||||
size_t h = metadata.height;
|
size_t h = metadata.height;
|
||||||
size_t d = metadata.depth;
|
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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -201,19 +210,19 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
|
|||||||
++index;
|
++index;
|
||||||
|
|
||||||
pixels += slicePitch;
|
pixels += slicePitch;
|
||||||
if ( pixels > pEndBits )
|
if (pixels > pEndBits)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( h > 1 )
|
if (h > 1)
|
||||||
h >>= 1;
|
h >>= 1;
|
||||||
|
|
||||||
if ( w > 1 )
|
if (w > 1)
|
||||||
w >>= 1;
|
w >>= 1;
|
||||||
|
|
||||||
if ( d > 1 )
|
if (d > 1)
|
||||||
d >>= 1;
|
d >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,20 +240,20 @@ bool _SetupImageArray( uint8_t *pMemory, size_t pixelSize,
|
|||||||
|
|
||||||
ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
|
ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
|
||||||
{
|
{
|
||||||
if ( this != &moveFrom )
|
if (this != &moveFrom)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
|
|
||||||
_nimages = moveFrom._nimages;
|
m_nimages = moveFrom.m_nimages;
|
||||||
_size = moveFrom._size;
|
m_size = moveFrom.m_size;
|
||||||
_metadata = moveFrom._metadata;
|
m_metadata = moveFrom.m_metadata;
|
||||||
_image = moveFrom._image;
|
m_image = moveFrom.m_image;
|
||||||
_memory = moveFrom._memory;
|
m_memory = moveFrom.m_memory;
|
||||||
|
|
||||||
moveFrom._nimages = 0;
|
moveFrom.m_nimages = 0;
|
||||||
moveFrom._size = 0;
|
moveFrom.m_size = 0;
|
||||||
moveFrom._image = nullptr;
|
moveFrom.m_image = nullptr;
|
||||||
moveFrom._memory = nullptr;
|
moveFrom.m_memory = nullptr;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -254,82 +263,82 @@ ScratchImage& ScratchImage::operator= (ScratchImage&& moveFrom)
|
|||||||
// Methods
|
// Methods
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsPalettized(mdata.format) )
|
if (IsPalettized(mdata.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
size_t mipLevels = mdata.mipLevels;
|
size_t mipLevels = mdata.mipLevels;
|
||||||
|
|
||||||
switch( mdata.dimension )
|
switch (mdata.dimension)
|
||||||
{
|
{
|
||||||
case TEX_DIMENSION_TEXTURE1D:
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( !_CalculateMipLevels(mdata.width,1,mipLevels) )
|
if (!_CalculateMipLevels(mdata.width, 1, mipLevels))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEX_DIMENSION_TEXTURE2D:
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( mdata.IsCubemap() )
|
if (mdata.IsCubemap())
|
||||||
{
|
{
|
||||||
if ( (mdata.arraySize % 6) != 0 )
|
if ((mdata.arraySize % 6) != 0)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !_CalculateMipLevels(mdata.width,mdata.height,mipLevels) )
|
if (!_CalculateMipLevels(mdata.width, mdata.height, mipLevels))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEX_DIMENSION_TEXTURE3D:
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( !_CalculateMipLevels3D(mdata.width,mdata.height,mdata.depth,mipLevels) )
|
if (!_CalculateMipLevels3D(mdata.width, mdata.height, mdata.depth, mipLevels))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
Release();
|
Release();
|
||||||
|
|
||||||
_metadata.width = mdata.width;
|
m_metadata.width = mdata.width;
|
||||||
_metadata.height = mdata.height;
|
m_metadata.height = mdata.height;
|
||||||
_metadata.depth = mdata.depth;
|
m_metadata.depth = mdata.depth;
|
||||||
_metadata.arraySize = mdata.arraySize;
|
m_metadata.arraySize = mdata.arraySize;
|
||||||
_metadata.mipLevels = mipLevels;
|
m_metadata.mipLevels = mipLevels;
|
||||||
_metadata.miscFlags = mdata.miscFlags;
|
m_metadata.miscFlags = mdata.miscFlags;
|
||||||
_metadata.miscFlags2 = mdata.miscFlags2;
|
m_metadata.miscFlags2 = mdata.miscFlags2;
|
||||||
_metadata.format = mdata.format;
|
m_metadata.format = mdata.format;
|
||||||
_metadata.dimension = mdata.dimension;
|
m_metadata.dimension = mdata.dimension;
|
||||||
|
|
||||||
size_t pixelSize, nimages;
|
size_t pixelSize, nimages;
|
||||||
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
|
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
|
||||||
|
|
||||||
_image = new (std::nothrow) Image[ nimages ];
|
m_image = new (std::nothrow) Image[nimages];
|
||||||
if ( !_image )
|
if (!m_image)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
_nimages = nimages;
|
m_nimages = nimages;
|
||||||
memset( _image, 0, sizeof(Image) * nimages );
|
memset(m_image, 0, sizeof(Image) * nimages);
|
||||||
|
|
||||||
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
|
m_memory = reinterpret_cast<uint8_t*>(_aligned_malloc(pixelSize, 16));
|
||||||
if ( !_memory )
|
if (!m_memory)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
return E_OUTOFMEMORY;
|
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();
|
Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -339,63 +348,63 @@ HRESULT ScratchImage::Initialize( const TexMetadata& mdata, DWORD flags )
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
// 1D is a special case of the 2D case
|
// 1D is a special case of the 2D case
|
||||||
HRESULT hr = Initialize2D( fmt, length, 1, arraySize, mipLevels, flags );
|
HRESULT hr = Initialize2D(fmt, length, 1, arraySize, mipLevels, flags);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
_metadata.dimension = TEX_DIMENSION_TEXTURE1D;
|
m_metadata.dimension = TEX_DIMENSION_TEXTURE1D;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsPalettized(fmt) )
|
if (IsPalettized(fmt))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
if ( !_CalculateMipLevels(width,height,mipLevels) )
|
if (!_CalculateMipLevels(width, height, mipLevels))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
Release();
|
Release();
|
||||||
|
|
||||||
_metadata.width = width;
|
m_metadata.width = width;
|
||||||
_metadata.height = height;
|
m_metadata.height = height;
|
||||||
_metadata.depth = 1;
|
m_metadata.depth = 1;
|
||||||
_metadata.arraySize = arraySize;
|
m_metadata.arraySize = arraySize;
|
||||||
_metadata.mipLevels = mipLevels;
|
m_metadata.mipLevels = mipLevels;
|
||||||
_metadata.miscFlags = 0;
|
m_metadata.miscFlags = 0;
|
||||||
_metadata.miscFlags2 = 0;
|
m_metadata.miscFlags2 = 0;
|
||||||
_metadata.format = fmt;
|
m_metadata.format = fmt;
|
||||||
_metadata.dimension = TEX_DIMENSION_TEXTURE2D;
|
m_metadata.dimension = TEX_DIMENSION_TEXTURE2D;
|
||||||
|
|
||||||
size_t pixelSize, nimages;
|
size_t pixelSize, nimages;
|
||||||
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
|
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
|
||||||
|
|
||||||
_image = new (std::nothrow) Image[ nimages ];
|
m_image = new (std::nothrow) Image[nimages];
|
||||||
if ( !_image )
|
if (!m_image)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
_nimages = nimages;
|
m_nimages = nimages;
|
||||||
memset( _image, 0, sizeof(Image) * nimages );
|
memset(m_image, 0, sizeof(Image) * nimages);
|
||||||
|
|
||||||
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
|
m_memory = reinterpret_cast<uint8_t*>(_aligned_malloc(pixelSize, 16));
|
||||||
if ( !_memory )
|
if (!m_memory)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
return E_OUTOFMEMORY;
|
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();
|
Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -405,50 +414,50 @@ HRESULT ScratchImage::Initialize2D( DXGI_FORMAT fmt, size_t width, size_t height
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsPalettized(fmt) )
|
if (IsPalettized(fmt))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
if ( !_CalculateMipLevels3D(width,height,depth,mipLevels) )
|
if (!_CalculateMipLevels3D(width, height, depth, mipLevels))
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
Release();
|
Release();
|
||||||
|
|
||||||
_metadata.width = width;
|
m_metadata.width = width;
|
||||||
_metadata.height = height;
|
m_metadata.height = height;
|
||||||
_metadata.depth = depth;
|
m_metadata.depth = depth;
|
||||||
_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
|
m_metadata.arraySize = 1; // Direct3D 10.x/11 does not support arrays of 3D textures
|
||||||
_metadata.mipLevels = mipLevels;
|
m_metadata.mipLevels = mipLevels;
|
||||||
_metadata.miscFlags = 0;
|
m_metadata.miscFlags = 0;
|
||||||
_metadata.miscFlags2 = 0;
|
m_metadata.miscFlags2 = 0;
|
||||||
_metadata.format = fmt;
|
m_metadata.format = fmt;
|
||||||
_metadata.dimension = TEX_DIMENSION_TEXTURE3D;
|
m_metadata.dimension = TEX_DIMENSION_TEXTURE3D;
|
||||||
|
|
||||||
size_t pixelSize, nimages;
|
size_t pixelSize, nimages;
|
||||||
_DetermineImageArray( _metadata, flags, nimages, pixelSize );
|
_DetermineImageArray(m_metadata, flags, nimages, pixelSize);
|
||||||
|
|
||||||
_image = new (std::nothrow) Image[ nimages ];
|
m_image = new (std::nothrow) Image[nimages];
|
||||||
if ( !_image )
|
if (!m_image)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
_nimages = nimages;
|
m_nimages = nimages;
|
||||||
memset( _image, 0, sizeof(Image) * nimages );
|
memset(m_image, 0, sizeof(Image) * nimages);
|
||||||
|
|
||||||
_memory = reinterpret_cast<uint8_t*>( _aligned_malloc( pixelSize, 16 ) );
|
m_memory = reinterpret_cast<uint8_t*>(_aligned_malloc(pixelSize, 16));
|
||||||
if ( !_memory )
|
if (!m_memory)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
return E_OUTOFMEMORY;
|
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();
|
Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -458,51 +467,51 @@ HRESULT ScratchImage::Initialize3D( DXGI_FORMAT fmt, size_t width, size_t height
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
// A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
|
// 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 );
|
HRESULT hr = Initialize2D(fmt, width, height, nCubes * 6, mipLevels, flags);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
|
m_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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 )
|
HRESULT hr = (srcImage.height > 1 || !allow1D)
|
||||||
? Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1, flags )
|
? Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1, flags)
|
||||||
: Initialize1D( srcImage.format, srcImage.width, 1, 1, flags );
|
: Initialize1D(srcImage.format, srcImage.width, 1, 1, flags);
|
||||||
|
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
size_t rowCount = ComputeScanlines( srcImage.format, srcImage.height );
|
size_t rowCount = ComputeScanlines(srcImage.format, srcImage.height);
|
||||||
if ( !rowCount )
|
if (!rowCount)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
const uint8_t* sptr = reinterpret_cast<const uint8_t*>( srcImage.pixels );
|
const uint8_t* sptr = reinterpret_cast<const uint8_t*>(srcImage.pixels);
|
||||||
if ( !sptr )
|
if (!sptr)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
auto dptr = reinterpret_cast<uint8_t*>( _image[0].pixels );
|
auto dptr = reinterpret_cast<uint8_t*>(m_image[0].pixels);
|
||||||
if ( !dptr )
|
if (!dptr)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
size_t spitch = srcImage.rowPitch;
|
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;
|
sptr += spitch;
|
||||||
dptr += dpitch;
|
dptr += dpitch;
|
||||||
}
|
}
|
||||||
@ -511,57 +520,57 @@ HRESULT ScratchImage::InitializeFromImage( const Image& srcImage, bool allow1D,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
DXGI_FORMAT format = images[0].format;
|
DXGI_FORMAT format = images[0].format;
|
||||||
size_t width = images[0].width;
|
size_t width = images[0].width;
|
||||||
size_t height = images[0].height;
|
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;
|
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
|
// All images must be the same format, width, and height
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = ( height > 1 || !allow1D )
|
HRESULT hr = (height > 1 || !allow1D)
|
||||||
? Initialize2D( format, width, height, nImages, 1, flags )
|
? Initialize2D(format, width, height, nImages, 1, flags)
|
||||||
: Initialize1D( format, width, nImages, 1, flags );
|
: Initialize1D(format, width, nImages, 1, flags);
|
||||||
|
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
size_t rowCount = ComputeScanlines( format, height );
|
size_t rowCount = ComputeScanlines(format, height);
|
||||||
if ( !rowCount )
|
if (!rowCount)
|
||||||
return E_UNEXPECTED;
|
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 );
|
auto sptr = reinterpret_cast<const uint8_t*>(images[index].pixels);
|
||||||
if ( !sptr )
|
if (!sptr)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( index < _nimages );
|
assert(index < m_nimages);
|
||||||
auto dptr = reinterpret_cast<uint8_t*>( _image[index].pixels );
|
auto dptr = reinterpret_cast<uint8_t*>(m_image[index].pixels);
|
||||||
if ( !dptr )
|
if (!dptr)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
size_t spitch = images[index].rowPitch;
|
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;
|
sptr += spitch;
|
||||||
dptr += dpitch;
|
dptr += dpitch;
|
||||||
}
|
}
|
||||||
@ -571,73 +580,73 @@ HRESULT ScratchImage::InitializeArrayFromImages( const Image* images, size_t nIm
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
// A DirectX11 cubemap is just a 2D texture array that is a multiple of 6 for each cube
|
// 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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
HRESULT hr = InitializeArrayFromImages( images, nImages, false, flags );
|
HRESULT hr = InitializeArrayFromImages(images, nImages, false, flags);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
|
m_metadata.miscFlags |= TEX_MISC_TEXTURECUBE;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
DXGI_FORMAT format = images[0].format;
|
DXGI_FORMAT format = images[0].format;
|
||||||
size_t width = images[0].width;
|
size_t width = images[0].width;
|
||||||
size_t height = images[0].height;
|
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;
|
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
|
// All images must be the same format, width, and height
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = Initialize3D( format, width, height, depth, 1, flags );
|
HRESULT hr = Initialize3D(format, width, height, depth, 1, flags);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
size_t rowCount = ComputeScanlines( format, height );
|
size_t rowCount = ComputeScanlines(format, height);
|
||||||
if ( !rowCount )
|
if (!rowCount)
|
||||||
return E_UNEXPECTED;
|
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 );
|
auto sptr = reinterpret_cast<const uint8_t*>(images[slice].pixels);
|
||||||
if ( !sptr )
|
if (!sptr)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( slice < _nimages );
|
assert(slice < m_nimages);
|
||||||
auto dptr = reinterpret_cast<uint8_t*>( _image[slice].pixels );
|
auto dptr = reinterpret_cast<uint8_t*>(m_image[slice].pixels);
|
||||||
if ( !dptr )
|
if (!dptr)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
size_t spitch = images[slice].rowPitch;
|
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;
|
sptr += spitch;
|
||||||
dptr += dpitch;
|
dptr += dpitch;
|
||||||
}
|
}
|
||||||
@ -648,39 +657,39 @@ HRESULT ScratchImage::Initialize3DFromImages( const Image* images, size_t depth,
|
|||||||
|
|
||||||
void ScratchImage::Release()
|
void ScratchImage::Release()
|
||||||
{
|
{
|
||||||
_nimages = 0;
|
m_nimages = 0;
|
||||||
_size = 0;
|
m_size = 0;
|
||||||
|
|
||||||
if ( _image )
|
if (m_image)
|
||||||
{
|
{
|
||||||
delete [] _image;
|
delete[] m_image;
|
||||||
_image = 0;
|
m_image = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _memory )
|
if (m_memory)
|
||||||
{
|
{
|
||||||
_aligned_free( _memory );
|
_aligned_free(m_memory);
|
||||||
_memory = 0;
|
m_memory = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&_metadata, 0, sizeof(_metadata));
|
memset(&m_metadata, 0, sizeof(m_metadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
|
bool ScratchImage::OverrideFormat(DXGI_FORMAT f)
|
||||||
{
|
{
|
||||||
if ( !_image )
|
if (!m_image)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( !IsValid( f ) || IsPlanar( f ) || IsPalettized( f ) )
|
if (!IsValid(f) || IsPlanar(f) || IsPalettized(f))
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -688,42 +697,42 @@ bool ScratchImage::OverrideFormat( DXGI_FORMAT f )
|
|||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
|
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;
|
return nullptr;
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
|
|
||||||
switch( _metadata.dimension )
|
switch (m_metadata.dimension)
|
||||||
{
|
{
|
||||||
case TEX_DIMENSION_TEXTURE1D:
|
case TEX_DIMENSION_TEXTURE1D:
|
||||||
case TEX_DIMENSION_TEXTURE2D:
|
case TEX_DIMENSION_TEXTURE2D:
|
||||||
if ( slice > 0 )
|
if (slice > 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if ( item >= _metadata.arraySize )
|
if (item >= m_metadata.arraySize)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
index = item*( _metadata.mipLevels ) + mip;
|
index = item*(m_metadata.mipLevels) + mip;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TEX_DIMENSION_TEXTURE3D:
|
case TEX_DIMENSION_TEXTURE3D:
|
||||||
if ( item > 0 )
|
if (item > 0)
|
||||||
{
|
{
|
||||||
// No support for arrays of volumes
|
// No support for arrays of volumes
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else
|
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;
|
index += d;
|
||||||
if ( d > 1 )
|
if (d > 1)
|
||||||
d >>= 1;
|
d >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( slice >= d )
|
if (slice >= d)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
index += slice;
|
index += slice;
|
||||||
@ -734,51 +743,51 @@ const Image* ScratchImage::GetImage(size_t mip, size_t item, size_t slice) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &_image[index];
|
return &m_image[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScratchImage::IsAlphaAllOpaque() const
|
bool ScratchImage::IsAlphaAllOpaque() const
|
||||||
{
|
{
|
||||||
if ( !_image )
|
if (!m_image)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( !HasAlpha( _metadata.format ) )
|
if (!HasAlpha(m_metadata.format))
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*_metadata.width), 16 ) ) );
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*m_metadata.width), 16)));
|
||||||
if ( !scanline )
|
if (!scanline)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
|
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 )
|
#pragma warning( suppress : 6011 )
|
||||||
const Image& img = _image[ index ];
|
const Image& img = m_image[index];
|
||||||
|
|
||||||
const uint8_t *pPixels = img.pixels;
|
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;
|
return false;
|
||||||
|
|
||||||
XMVECTOR* ptr = scanline.get();
|
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 );
|
XMVECTOR alpha = XMVectorSplatW(*ptr);
|
||||||
if ( XMVector4Less( alpha, threshold ) )
|
if (XMVector4Less(alpha, threshold))
|
||||||
return false;
|
return false;
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
@ -790,5 +799,3 @@ bool ScratchImage::IsAlphaAllOpaque() const
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,29 +15,34 @@
|
|||||||
|
|
||||||
#include "directxtexp.h"
|
#include "directxtexp.h"
|
||||||
|
|
||||||
namespace DirectX
|
using namespace DirectX;
|
||||||
{
|
|
||||||
static const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
namespace
|
||||||
static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
|
|
||||||
_Out_ float& mse, _Out_writes_opt_(4) float* mseV,
|
|
||||||
_In_ DWORD flags )
|
|
||||||
{
|
{
|
||||||
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;
|
return E_POINTER;
|
||||||
|
|
||||||
assert( image1.width == image2.width && image1.height == image2.height );
|
assert(image1.width == image2.width && image1.height == image2.height);
|
||||||
assert( !IsCompressed( image1.format ) && !IsCompressed( image2.format ) );
|
assert(!IsCompressed(image1.format) && !IsCompressed(image2.format));
|
||||||
|
|
||||||
const size_t width = image1.width;
|
const size_t width = image1.width;
|
||||||
|
|
||||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width)*2, 16 ) ) );
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width) * 2, 16)));
|
||||||
if ( !scanline )
|
if (!scanline)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
// Flags implied from image formats
|
// Flags implied from image formats
|
||||||
switch( image1.format )
|
switch (image1.format)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||||
flags |= CMSE_IGNORE_ALPHA;
|
flags |= CMSE_IGNORE_ALPHA;
|
||||||
@ -57,7 +62,7 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( image2.format )
|
switch (image2.format)
|
||||||
{
|
{
|
||||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||||
flags |= CMSE_IGNORE_ALPHA;
|
flags |= CMSE_IGNORE_ALPHA;
|
||||||
@ -86,58 +91,58 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
|
|||||||
XMVECTOR acc = g_XMZero;
|
XMVECTOR acc = g_XMZero;
|
||||||
static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
|
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();
|
XMVECTOR* ptr1 = scanline.get();
|
||||||
if ( !_LoadScanline( ptr1, width, pSrc1, rowPitch1, image1.format ) )
|
if (!_LoadScanline(ptr1, width, pSrc1, rowPitch1, image1.format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
XMVECTOR* ptr2 = scanline.get() + width;
|
XMVECTOR* ptr2 = scanline.get() + width;
|
||||||
if ( !_LoadScanline( ptr2, width, pSrc2, rowPitch2, image2.format ) )
|
if (!_LoadScanline(ptr2, width, pSrc2, rowPitch2, image2.format))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
for( size_t i = 0; i < width; ++i )
|
for (size_t i = 0; i < width; ++i)
|
||||||
{
|
{
|
||||||
XMVECTOR v1 = *(ptr1++);
|
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++);
|
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 ]
|
// sum[ (I1 - I2)^2 ]
|
||||||
XMVECTOR v = XMVectorSubtract( v1, v2 );
|
XMVECTOR v = XMVectorSubtract(v1, v2);
|
||||||
if ( flags & CMSE_IGNORE_RED )
|
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;
|
pSrc1 += rowPitch1;
|
||||||
@ -145,22 +150,23 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MSE = sum[ (I1 - I2)^2 ] / w*h
|
// MSE = sum[ (I1 - I2)^2 ] / w*h
|
||||||
XMVECTOR d = XMVectorReplicate( float(image1.width * image1.height) );
|
XMVECTOR d = XMVectorReplicate(float(image1.width * image1.height));
|
||||||
XMVECTOR v = XMVectorDivide( acc, d );
|
XMVECTOR v = XMVectorDivide(acc, d);
|
||||||
if ( mseV )
|
if (mseV)
|
||||||
{
|
{
|
||||||
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( mseV ), v );
|
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(mseV), v);
|
||||||
mse = mseV[0] + mseV[1] + mseV[2] + mseV[3];
|
mse = mseV[0] + mseV[1] + mseV[2] + mseV[3];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
XMFLOAT4 _mseV;
|
XMFLOAT4 _mseV;
|
||||||
XMStoreFloat4( &_mseV, v );
|
XMStoreFloat4(&_mseV, v);
|
||||||
mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w;
|
mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
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
|
// Copies a rectangle from one image into another
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_POINTER;
|
||||||
|
|
||||||
if ( IsCompressed( srcImage.format ) || IsCompressed( dstImage.format )
|
if (IsCompressed(srcImage.format) || IsCompressed(dstImage.format)
|
||||||
|| IsPlanar( srcImage.format ) || IsPlanar( dstImage.format )
|
|| IsPlanar(srcImage.format) || IsPlanar(dstImage.format)
|
||||||
|| IsPalettized( srcImage.format ) || IsPalettized( dstImage.format ) )
|
|| IsPalettized(srcImage.format) || IsPalettized(dstImage.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
// Validate rectangle/offset
|
// 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;
|
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;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute source bytes-per-pixel
|
// Compute source bytes-per-pixel
|
||||||
size_t sbpp = BitsPerPixel( srcImage.format );
|
size_t sbpp = BitsPerPixel(srcImage.format);
|
||||||
if ( !sbpp )
|
if (!sbpp)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( sbpp < 8 )
|
if (sbpp < 8)
|
||||||
{
|
{
|
||||||
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
|
// 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* pEndSrc = srcImage.pixels + srcImage.rowPitch*srcImage.height;
|
||||||
const uint8_t* pEndDest = dstImage.pixels + dstImage.rowPitch*dstImage.height;
|
const uint8_t* pEndDest = dstImage.pixels + dstImage.rowPitch*dstImage.height;
|
||||||
|
|
||||||
// Round to bytes
|
// Round to bytes
|
||||||
sbpp = ( sbpp + 7 ) / 8;
|
sbpp = (sbpp + 7) / 8;
|
||||||
|
|
||||||
const uint8_t* pSrc = srcImage.pixels + (srcRect.y * srcImage.rowPitch) + (srcRect.x * sbpp);
|
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)
|
// Direct copy case (avoid intermediate conversions)
|
||||||
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * sbpp);
|
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * sbpp);
|
||||||
const size_t copyW = srcRect.w * 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;
|
return E_FAIL;
|
||||||
|
|
||||||
memcpy_s( pDest, pEndDest - pDest, pSrc, copyW );
|
memcpy_s(pDest, pEndDest - pDest, pSrc, copyW);
|
||||||
|
|
||||||
pSrc += srcImage.rowPitch;
|
pSrc += srcImage.rowPitch;
|
||||||
pDest += dstImage.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)
|
// Compute destination bytes-per-pixel (not the same format as source)
|
||||||
size_t dbpp = BitsPerPixel( dstImage.format );
|
size_t dbpp = BitsPerPixel(dstImage.format);
|
||||||
if ( !dbpp )
|
if (!dbpp)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( dbpp < 8 )
|
if (dbpp < 8)
|
||||||
{
|
{
|
||||||
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
|
// 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
|
// Round to bytes
|
||||||
dbpp = ( dbpp + 7 ) / 8;
|
dbpp = (dbpp + 7) / 8;
|
||||||
|
|
||||||
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * dbpp);
|
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * dbpp);
|
||||||
|
|
||||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcRect.w), 16 ) ) );
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcRect.w), 16)));
|
||||||
if ( !scanline )
|
if (!scanline)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
const size_t copyS = srcRect.w * sbpp;
|
const size_t copyS = srcRect.w * sbpp;
|
||||||
const size_t copyD = srcRect.w * dbpp;
|
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;
|
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;
|
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;
|
return E_FAIL;
|
||||||
|
|
||||||
pSrc += srcImage.rowPitch;
|
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
|
// Computes the Mean-Squared-Error (MSE) between two images
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_POINTER;
|
||||||
|
|
||||||
if ( image1.width != image2.width || image1.height != image2.height )
|
if (image1.width != image2.width || image1.height != image2.height)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsPlanar( image1.format ) || IsPlanar( image2.format )
|
if (IsPlanar(image1.format) || IsPlanar(image2.format)
|
||||||
|| IsPalettized( image1.format ) || IsPalettized( image2.format ) )
|
|| IsPalettized(image1.format) || IsPalettized(image2.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
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
|
// Case 1: both images are compressed, expand to RGBA32F
|
||||||
ScratchImage temp1;
|
ScratchImage temp1;
|
||||||
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1 );
|
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
ScratchImage temp2;
|
ScratchImage temp2;
|
||||||
hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2 );
|
hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image* img1 = temp1.GetImage(0,0,0);
|
const Image* img1 = temp1.GetImage(0, 0, 0);
|
||||||
const Image* img2 = temp2.GetImage(0,0,0);
|
const Image* img2 = temp2.GetImage(0, 0, 0);
|
||||||
if ( !img1 || !img2 )
|
if (!img1 || !img2)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
return _ComputeMSE( *img1, *img2, mse, mseV, flags );
|
return ComputeMSE_(*img1, *img2, mse, mseV, flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Case 2: image1 is compressed, expand to RGBA32F
|
// Case 2: image1 is compressed, expand to RGBA32F
|
||||||
ScratchImage temp;
|
ScratchImage temp;
|
||||||
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
|
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image* img = temp.GetImage(0,0,0);
|
const Image* img = temp.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
return _ComputeMSE( *img, image2, mse, mseV, flags );
|
return ComputeMSE_(*img, image2, mse, mseV, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( IsCompressed(image2.format) )
|
if (IsCompressed(image2.format))
|
||||||
{
|
{
|
||||||
// Case 3: image2 is compressed, expand to RGBA32F
|
// Case 3: image2 is compressed, expand to RGBA32F
|
||||||
ScratchImage temp;
|
ScratchImage temp;
|
||||||
HRESULT hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
|
HRESULT hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image* img = temp.GetImage(0,0,0);
|
const Image* img = temp.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
return _ComputeMSE( image1, *img, mse, mseV, flags );
|
return ComputeMSE_(image1, *img, mse, mseV, flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Case 4: neither image is compressed
|
// 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"
|
#include "directxtexp.h"
|
||||||
|
|
||||||
namespace DirectX
|
using namespace DirectX;
|
||||||
|
|
||||||
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
|
#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;
|
XMFLOAT4A f;
|
||||||
|
|
||||||
static XMVECTORF32 lScale = { 0.2125f, 0.7154f, 0.0721f, 1.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" );
|
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
|
||||||
switch( flags & 0xf )
|
switch (flags & 0xf)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case CNMAP_CHANNEL_RED: return XMVectorGetX( val );
|
case CNMAP_CHANNEL_RED: return XMVectorGetX(val);
|
||||||
case CNMAP_CHANNEL_GREEN: return XMVectorGetY( val );
|
case CNMAP_CHANNEL_GREEN: return XMVectorGetY(val);
|
||||||
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ( val );
|
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ(val);
|
||||||
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW( val );
|
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW(val);
|
||||||
|
|
||||||
case CNMAP_CHANNEL_LUMINANCE:
|
case CNMAP_CHANNEL_LUMINANCE:
|
||||||
{
|
{
|
||||||
XMVECTOR v = XMVectorMultiply( val, lScale );
|
XMVECTOR v = XMVectorMultiply(val, lScale);
|
||||||
XMStoreFloat4A( &f, v );
|
XMStoreFloat4A(&f, v);
|
||||||
return f.x + f.y + f.z;
|
return f.x + f.y + f.z;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -46,62 +48,65 @@ static inline float _EvaluateColor( _In_ FXMVECTOR val, _In_ DWORD flags )
|
|||||||
assert(false);
|
assert(false);
|
||||||
return 0.f;
|
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
|
// Mirror in U
|
||||||
pDest[0] = _EvaluateColor( pSource[0], flags );
|
pDest[0] = EvaluateColor(pSource[0], flags);
|
||||||
pDest[width+1] = _EvaluateColor( pSource[width-1], flags );
|
pDest[width + 1] = EvaluateColor(pSource[width - 1], flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Wrap in U
|
// Wrap in U
|
||||||
pDest[0] = _EvaluateColor( pSource[width-1], flags );
|
pDest[0] = EvaluateColor(pSource[width - 1], flags);
|
||||||
pDest[width+1] = _EvaluateColor( pSource[0], flags );
|
pDest[width + 1] = EvaluateColor(pSource[0], flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
|
HRESULT ComputeNMap(_In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
|
||||||
_In_ DXGI_FORMAT format, _In_ const Image& normalMap )
|
_In_ DXGI_FORMAT format, _In_ const Image& normalMap)
|
||||||
{
|
{
|
||||||
if ( !srcImage.pixels || !normalMap.pixels )
|
if (!srcImage.pixels || !normalMap.pixels)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
const DWORD convFlags = _GetConvertFlags( format );
|
const DWORD convFlags = _GetConvertFlags(format);
|
||||||
if ( !convFlags )
|
if (!convFlags)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if ( !( convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT) ) )
|
if (!(convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT)))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
const size_t width = srcImage.width;
|
const size_t width = srcImage.width;
|
||||||
const size_t height = srcImage.height;
|
const size_t height = srcImage.height;
|
||||||
if ( width != normalMap.width || height != normalMap.height )
|
if (width != normalMap.width || height != normalMap.height)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
// Allocate temporary space (4 scanlines and 3 evaluated rows)
|
// Allocate temporary space (4 scanlines and 3 evaluated rows)
|
||||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*4), 16 ) ) );
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width * 4), 16)));
|
||||||
if ( !scanline )
|
if (!scanline)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
ScopedAlignedArrayFloat buffer( reinterpret_cast<float*>( _aligned_malloc( ( ( sizeof(float) * ( width + 2 ) ) * 3 ), 16 ) ) );
|
ScopedAlignedArrayFloat buffer(reinterpret_cast<float*>(_aligned_malloc(((sizeof(float) * (width + 2)) * 3), 16)));
|
||||||
if ( !buffer )
|
if (!buffer)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
uint8_t* pDest = normalMap.pixels;
|
uint8_t* pDest = normalMap.pixels;
|
||||||
if ( !pDest )
|
if (!pDest)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
XMVECTOR* row0 = scanline.get();
|
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;
|
const uint8_t* pSrc = srcImage.pixels;
|
||||||
|
|
||||||
// Read first scanline row into 'row1'
|
// 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;
|
return E_FAIL;
|
||||||
|
|
||||||
// Setup 'row0'
|
// Setup 'row0'
|
||||||
if ( flags & CNMAP_MIRROR_V )
|
if (flags & CNMAP_MIRROR_V)
|
||||||
{
|
{
|
||||||
// Mirror first row
|
// Mirror first row
|
||||||
memcpy_s( row0, rowPitch, row1, rowPitch );
|
memcpy_s(row0, rowPitch, row1, rowPitch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Read last row (Wrap V)
|
// 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;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the initial rows
|
// Evaluate the initial rows
|
||||||
_EvaluateRow( row0, val0, width, flags );
|
EvaluateRow(row0, val0, width, flags);
|
||||||
_EvaluateRow( row1, val1, width, flags );
|
EvaluateRow(row1, val1, width, flags);
|
||||||
|
|
||||||
pSrc += rowPitch;
|
pSrc += rowPitch;
|
||||||
|
|
||||||
for( size_t y = 0; y < height; ++y )
|
for (size_t y = 0; y < height; ++y)
|
||||||
{
|
{
|
||||||
// Load next scanline of source image
|
// 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;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( flags & CNMAP_MIRROR_V )
|
if (flags & CNMAP_MIRROR_V)
|
||||||
{
|
{
|
||||||
// Use last row of source image
|
// 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;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Use first row of source image (Wrap V)
|
// 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;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate row
|
// Evaluate row
|
||||||
_EvaluateRow( row2, val2, width, flags );
|
EvaluateRow(row2, val2, width, flags);
|
||||||
|
|
||||||
// Generate target scanline
|
// Generate target scanline
|
||||||
XMVECTOR *dptr = target;
|
XMVECTOR *dptr = target;
|
||||||
for( size_t x = 0; x < width; ++x )
|
for (size_t x = 0; x < width; ++x)
|
||||||
{
|
{
|
||||||
// Compute normal via central differencing
|
// 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;
|
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;
|
float deltaZY = totDelta * amplitude / 6.f;
|
||||||
|
|
||||||
XMVECTOR vx = XMVectorSetZ( g_XMNegIdentityR0, deltaZX ); // (-1.0f, 0.0f, deltaZX)
|
XMVECTOR vx = XMVectorSetZ(g_XMNegIdentityR0, deltaZX); // (-1.0f, 0.0f, deltaZX)
|
||||||
XMVECTOR vy = XMVectorSetZ( g_XMNegIdentityR1, deltaZY ); // (0.0f, -1.0f, deltaZY)
|
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)
|
// Compute alpha (1.0 or an occlusion term)
|
||||||
float alpha = 1.f;
|
float alpha = 1.f;
|
||||||
|
|
||||||
if ( flags & CNMAP_COMPUTE_OCCLUSION )
|
if (flags & CNMAP_COMPUTE_OCCLUSION)
|
||||||
{
|
{
|
||||||
float delta = 0.f;
|
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;
|
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 + 1] - c; if (t > 0.f) delta += t;
|
||||||
t = val0[x+2] - 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;
|
t = val1[x] - c; if (t > 0.f) delta += t;
|
||||||
// Skip current pixel
|
// Skip current pixel
|
||||||
t = val1[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] - c; if (t > 0.f) delta += t;
|
||||||
t = val2[x+1] - 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 = val2[x + 2] - c; if (t > 0.f) delta += t;
|
||||||
|
|
||||||
// Average delta (divide by 8, scale by amplitude factor)
|
// Average delta (divide by 8, scale by amplitude factor)
|
||||||
delta *= 0.125f * amplitude;
|
delta *= 0.125f * amplitude;
|
||||||
if ( delta > 0.f )
|
if (delta > 0.f)
|
||||||
{
|
{
|
||||||
// If < 0, then no occlusion
|
// If < 0, then no occlusion
|
||||||
float r = sqrtf( 1.f + delta*delta );
|
float r = sqrtf(1.f + delta*delta);
|
||||||
alpha = (r - delta) / r;
|
alpha = (r - delta) / r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode based on target format
|
// 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
|
// 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 );
|
XMVECTOR n1 = XMVectorMultiplyAdd((flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf);
|
||||||
*dptr++ = XMVectorSetW( n1, alpha );
|
*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
|
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;
|
return E_FAIL;
|
||||||
|
|
||||||
// Cycle buffers
|
// Cycle buffers
|
||||||
@ -241,6 +246,7 @@ static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_
|
|||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
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
|
// Generates a normal map from a height-map
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
|
HRESULT DirectX::ComputeNormalMap(
|
||||||
DXGI_FORMAT format, ScratchImage& normalMap )
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
|
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
|
||||||
switch( flags & 0xf )
|
switch (flags & 0xf)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case CNMAP_CHANNEL_RED:
|
case CNMAP_CHANNEL_RED:
|
||||||
@ -273,28 +283,28 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
|
|||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( IsCompressed(format) || IsCompressed(srcImage.format)
|
if (IsCompressed(format) || IsCompressed(srcImage.format)
|
||||||
|| IsTypeless(format) || IsTypeless(srcImage.format)
|
|| IsTypeless(format) || IsTypeless(srcImage.format)
|
||||||
|| IsPlanar(format) || IsPlanar(srcImage.format)
|
|| IsPlanar(format) || IsPlanar(srcImage.format)
|
||||||
|| IsPalettized(format) || IsPalettized(srcImage.format) )
|
|| IsPalettized(format) || IsPalettized(srcImage.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
// Setup target image
|
// Setup target image
|
||||||
normalMap.Release();
|
normalMap.Release();
|
||||||
|
|
||||||
HRESULT hr = normalMap.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
|
HRESULT hr = normalMap.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *img = normalMap.GetImage( 0, 0, 0 );
|
const Image *img = normalMap.GetImage(0, 0, 0);
|
||||||
if ( !img )
|
if (!img)
|
||||||
{
|
{
|
||||||
normalMap.Release();
|
normalMap.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _ComputeNMap( srcImage, flags, amplitude, format, *img );
|
hr = ComputeNMap(srcImage, flags, amplitude, format, *img);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
normalMap.Release();
|
normalMap.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -304,20 +314,26 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
|
HRESULT DirectX::ComputeNormalMap(
|
||||||
DWORD flags, float amplitude, DXGI_FORMAT format, ScratchImage& normalMaps )
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsCompressed(format) || IsCompressed(metadata.format)
|
if (IsCompressed(format) || IsCompressed(metadata.format)
|
||||||
|| IsTypeless(format) || IsTypeless(metadata.format)
|
|| IsTypeless(format) || IsTypeless(metadata.format)
|
||||||
|| IsPlanar(format) || IsPlanar(metadata.format)
|
|| IsPlanar(format) || IsPlanar(metadata.format)
|
||||||
|| IsPalettized(format) || IsPalettized(metadata.format) )
|
|| IsPalettized(format) || IsPalettized(metadata.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||||
|
|
||||||
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
|
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
|
||||||
switch( flags & 0xf )
|
switch (flags & 0xf)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case CNMAP_CHANNEL_RED:
|
case CNMAP_CHANNEL_RED:
|
||||||
@ -335,42 +351,42 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
|
|||||||
|
|
||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
mdata2.format = format;
|
mdata2.format = format;
|
||||||
HRESULT hr = normalMaps.Initialize( mdata2 );
|
HRESULT hr = normalMaps.Initialize(mdata2);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if ( nimages != normalMaps.GetImageCount() )
|
if (nimages != normalMaps.GetImageCount())
|
||||||
{
|
{
|
||||||
normalMaps.Release();
|
normalMaps.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Image* dest = normalMaps.GetImages();
|
const Image* dest = normalMaps.GetImages();
|
||||||
if ( !dest )
|
if (!dest)
|
||||||
{
|
{
|
||||||
normalMaps.Release();
|
normalMaps.Release();
|
||||||
return E_POINTER;
|
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 ( IsCompressed( src.format ) || IsTypeless( src.format ) )
|
if (IsCompressed(src.format) || IsTypeless(src.format))
|
||||||
{
|
{
|
||||||
normalMaps.Release();
|
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();
|
normalMaps.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = _ComputeNMap( src, flags, amplitude, format, dest[ index ] );
|
hr = ComputeNMap(src, flags, amplitude, format, dest[index]);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
normalMaps.Release();
|
normalMaps.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -379,5 +395,3 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
|
|||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
|
||||||
|
@ -175,40 +175,40 @@ namespace DirectX
|
|||||||
|
|
||||||
void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
|
void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
|
||||||
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
|
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
|
||||||
LPVOID pDestination, _In_ size_t outSize,
|
void* pDestination, _In_ size_t outSize,
|
||||||
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
|
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
|
||||||
_In_ DXGI_FORMAT format, _In_ DWORD flags );
|
_In_ DXGI_FORMAT format, _In_ DWORD flags );
|
||||||
|
|
||||||
void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_)
|
void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_)
|
||||||
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
|
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
|
||||||
LPVOID pDestination, _In_ size_t outSize,
|
void* pDestination, _In_ size_t outSize,
|
||||||
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
|
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
|
||||||
_In_ DXGI_FORMAT format, _In_ DWORD flags );
|
_In_ DXGI_FORMAT format, _In_ DWORD flags );
|
||||||
|
|
||||||
_Success_(return != false)
|
_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_ 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 );
|
_In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
|
||||||
|
|
||||||
_Success_(return != false)
|
_Success_(return != false)
|
||||||
bool __cdecl _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
|
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)
|
_Success_(return != false)
|
||||||
bool __cdecl _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
|
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)
|
_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 );
|
_In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0 );
|
||||||
|
|
||||||
_Success_(return != false)
|
_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 );
|
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags, _In_ float threshold = 0 );
|
||||||
|
|
||||||
_Success_(return != false)
|
_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_(count) XMVECTOR* pSource, _In_ size_t count, _In_ float threshold, size_t y, size_t z,
|
||||||
_Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors );
|
_Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors );
|
||||||
|
|
||||||
@ -225,6 +225,6 @@ namespace DirectX
|
|||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
// DDS helper functions
|
// DDS helper functions
|
||||||
HRESULT __cdecl _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
|
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
|
}; // namespace
|
||||||
|
@ -15,38 +15,40 @@
|
|||||||
|
|
||||||
#include "directxtexp.h"
|
#include "directxtexp.h"
|
||||||
|
|
||||||
namespace DirectX
|
using namespace DirectX;
|
||||||
|
|
||||||
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& destImage )
|
HRESULT PremultiplyAlpha_(const Image& srcImage, const Image& destImage)
|
||||||
{
|
{
|
||||||
assert( srcImage.width == destImage.width );
|
assert(srcImage.width == destImage.width);
|
||||||
assert( srcImage.height == destImage.height );
|
assert(srcImage.height == destImage.height);
|
||||||
|
|
||||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
|
||||||
if ( !scanline )
|
if (!scanline)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
const uint8_t *pSrc = srcImage.pixels;
|
const uint8_t *pSrc = srcImage.pixels;
|
||||||
uint8_t *pDest = destImage.pixels;
|
uint8_t *pDest = destImage.pixels;
|
||||||
if ( !pSrc || !pDest )
|
if (!pSrc || !pDest)
|
||||||
return E_POINTER;
|
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;
|
return E_FAIL;
|
||||||
|
|
||||||
XMVECTOR* ptr = scanline.get();
|
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 v = *ptr;
|
||||||
XMVECTOR alpha = XMVectorSplatW( *ptr );
|
XMVECTOR alpha = XMVectorSplatW(*ptr);
|
||||||
alpha = XMVectorMultiply( v, alpha );
|
alpha = XMVectorMultiply(v, alpha);
|
||||||
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
|
*(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;
|
return E_FAIL;
|
||||||
|
|
||||||
pSrc += srcImage.rowPitch;
|
pSrc += srcImage.rowPitch;
|
||||||
@ -54,42 +56,42 @@ static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image&
|
|||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
|
HRESULT PremultiplyAlphaLinear(const Image& srcImage, DWORD flags, const Image& destImage)
|
||||||
{
|
{
|
||||||
assert( srcImage.width == destImage.width );
|
assert(srcImage.width == destImage.width);
|
||||||
assert( srcImage.height == destImage.height );
|
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_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_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 == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
|
||||||
flags &= TEX_PMALPHA_SRGB;
|
flags &= TEX_PMALPHA_SRGB;
|
||||||
|
|
||||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
|
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
|
||||||
if ( !scanline )
|
if (!scanline)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
const uint8_t *pSrc = srcImage.pixels;
|
const uint8_t *pSrc = srcImage.pixels;
|
||||||
uint8_t *pDest = destImage.pixels;
|
uint8_t *pDest = destImage.pixels;
|
||||||
if ( !pSrc || !pDest )
|
if (!pSrc || !pDest)
|
||||||
return E_POINTER;
|
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;
|
return E_FAIL;
|
||||||
|
|
||||||
XMVECTOR* ptr = scanline.get();
|
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 v = *ptr;
|
||||||
XMVECTOR alpha = XMVectorSplatW( *ptr );
|
XMVECTOR alpha = XMVectorSplatW(*ptr);
|
||||||
alpha = XMVectorMultiply( v, alpha );
|
alpha = XMVectorMultiply(v, alpha);
|
||||||
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
|
*(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;
|
return E_FAIL;
|
||||||
|
|
||||||
pSrc += srcImage.rowPitch;
|
pSrc += srcImage.rowPitch;
|
||||||
@ -97,6 +99,7 @@ static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD f
|
|||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
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
|
// Converts to a premultiplied alpha version of the texture
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_POINTER;
|
||||||
|
|
||||||
if ( IsCompressed(srcImage.format)
|
if (IsCompressed(srcImage.format)
|
||||||
|| IsPlanar(srcImage.format)
|
|| IsPlanar(srcImage.format)
|
||||||
|| IsPalettized(srcImage.format)
|
|| IsPalettized(srcImage.format)
|
||||||
|| IsTypeless(srcImage.format)
|
|| IsTypeless(srcImage.format)
|
||||||
|| !HasAlpha(srcImage.format) )
|
|| !HasAlpha(srcImage.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 );
|
HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
const Image *rimage = image.GetImage( 0, 0, 0 );
|
const Image *rimage = image.GetImage(0, 0, 0);
|
||||||
if ( !rimage )
|
if (!rimage)
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( srcImage, *rimage ) : _PremultiplyAlphaLinear( srcImage, flags, *rimage );
|
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(srcImage, *rimage) : PremultiplyAlphaLinear(srcImage, flags, *rimage);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
image.Release();
|
image.Release();
|
||||||
return hr;
|
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)
|
// Converts to a premultiplied alpha version of the texture (complex)
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( IsCompressed(metadata.format)
|
if (IsCompressed(metadata.format)
|
||||||
|| IsPlanar(metadata.format)
|
|| IsPlanar(metadata.format)
|
||||||
|| IsPalettized(metadata.format)
|
|| IsPalettized(metadata.format)
|
||||||
|| IsTypeless(metadata.format)
|
|| IsTypeless(metadata.format)
|
||||||
|| !HasAlpha(metadata.format) )
|
|| !HasAlpha(metadata.format))
|
||||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if ( metadata.IsPMAlpha() )
|
if (metadata.IsPMAlpha())
|
||||||
{
|
{
|
||||||
// Already premultiplied
|
// Already premultiplied
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
@ -172,46 +183,46 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
|
|||||||
|
|
||||||
TexMetadata mdata2 = metadata;
|
TexMetadata mdata2 = metadata;
|
||||||
mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED);
|
mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED);
|
||||||
HRESULT hr = result.Initialize( mdata2 );
|
HRESULT hr = result.Initialize(mdata2);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if ( nimages != result.GetImageCount() )
|
if (nimages != result.GetImageCount())
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Image* dest = result.GetImages();
|
const Image* dest = result.GetImages();
|
||||||
if ( !dest )
|
if (!dest)
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( size_t index=0; index < nimages; ++index )
|
for (size_t index = 0; index < nimages; ++index)
|
||||||
{
|
{
|
||||||
const Image& src = srcImages[ index ];
|
const Image& src = srcImages[index];
|
||||||
if ( src.format != metadata.format )
|
if (src.format != metadata.format)
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
|
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
const Image& dst = dest[ index ];
|
const Image& dst = dest[index];
|
||||||
assert( dst.format == metadata.format );
|
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();
|
result.Release();
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( src, dst ) : _PremultiplyAlphaLinear( src, flags, dst );
|
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(src, dst) : PremultiplyAlphaLinear(src, flags, dst);
|
||||||
if ( FAILED(hr) )
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
result.Release();
|
result.Release();
|
||||||
return hr;
|
return hr;
|
||||||
@ -220,5 +231,3 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
|
|||||||
|
|
||||||
return S_OK;
|
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"
|
#include "directxtexp.h"
|
||||||
|
|
||||||
using Microsoft::WRL::ComPtr;
|
|
||||||
|
|
||||||
#if defined(_XBOX_ONE) && defined(_TITLE)
|
#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_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");
|
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");
|
static_assert(WIN10_DXGI_FORMAT_V408 == DXGI_FORMAT_V408, "Windows SDK mismatch detected");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace DirectX;
|
||||||
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
namespace
|
||||||
// WIC Pixel Format Translation Data
|
|
||||||
//-------------------------------------------------------------------------------------
|
|
||||||
struct WICTranslate
|
|
||||||
{
|
{
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
// WIC Pixel Format Translation Data
|
||||||
|
//-------------------------------------------------------------------------------------
|
||||||
|
struct WICTranslate
|
||||||
|
{
|
||||||
GUID wic;
|
GUID wic;
|
||||||
DXGI_FORMAT format;
|
DXGI_FORMAT format;
|
||||||
bool srgb;
|
bool srgb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const WICTranslate g_WICFormats[] =
|
const WICTranslate g_WICFormats[] =
|
||||||
{
|
{
|
||||||
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
|
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
|
||||||
|
|
||||||
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_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_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM, false },
|
||||||
|
|
||||||
{ GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false },
|
{ GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool g_WIC2 = false;
|
bool g_WIC2 = false;
|
||||||
static IWICImagingFactory* g_Factory = nullptr;
|
IWICImagingFactory* g_Factory = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace DirectX
|
|
||||||
{
|
|
||||||
|
|
||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
// WIC Utilities
|
// WIC Utilities
|
||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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;
|
return g_WICFormats[i].format;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
#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;
|
return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -103,7 +103,7 @@ DXGI_FORMAT _WICToDXGI( const GUID& guid )
|
|||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
|
bool DirectX::_DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
|
||||||
{
|
{
|
||||||
switch( format )
|
switch( format )
|
||||||
{
|
{
|
||||||
@ -163,28 +163,28 @@ bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
|
|||||||
return false;
|
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;
|
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;
|
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;
|
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;
|
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
|
// Public helper function to get common WIC codec GUIDs
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
REFGUID GetWICCodec( WICCodecs codec )
|
REFGUID DirectX::GetWICCodec(WICCodecs codec)
|
||||||
{
|
{
|
||||||
switch( codec )
|
switch (codec)
|
||||||
{
|
{
|
||||||
case WIC_CODEC_BMP:
|
case WIC_CODEC_BMP:
|
||||||
return GUID_ContainerFormatBmp;
|
return GUID_ContainerFormatBmp;
|
||||||
@ -229,9 +229,9 @@ REFGUID GetWICCodec( WICCodecs codec )
|
|||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Singleton function for WIC factory
|
// Singleton function for WIC factory
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
IWICImagingFactory* GetWICFactory( bool& iswic2 )
|
IWICImagingFactory* DirectX::GetWICFactory(bool& iswic2)
|
||||||
{
|
{
|
||||||
if ( g_Factory )
|
if (g_Factory)
|
||||||
{
|
{
|
||||||
iswic2 = g_WIC2;
|
iswic2 = g_WIC2;
|
||||||
return g_Factory;
|
return g_Factory;
|
||||||
@ -240,9 +240,9 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
|
|||||||
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
|
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
|
||||||
|
|
||||||
InitOnceExecuteOnce(&s_initOnce,
|
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(
|
HRESULT hr = CoCreateInstance(
|
||||||
CLSID_WICImagingFactory2,
|
CLSID_WICImagingFactory2,
|
||||||
nullptr,
|
nullptr,
|
||||||
@ -270,17 +270,17 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
|
|||||||
);
|
);
|
||||||
return SUCCEEDED(hr) ? TRUE : FALSE;
|
return SUCCEEDED(hr) ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
g_WIC2 = false;
|
g_WIC2 = false;
|
||||||
|
|
||||||
return SUCCEEDED( CoCreateInstance(
|
return SUCCEEDED(CoCreateInstance(
|
||||||
CLSID_WICImagingFactory,
|
CLSID_WICImagingFactory,
|
||||||
nullptr,
|
nullptr,
|
||||||
CLSCTX_INPROC_SERVER,
|
CLSCTX_INPROC_SERVER,
|
||||||
__uuidof(IWICImagingFactory),
|
__uuidof(IWICImagingFactory),
|
||||||
factory) ) ? TRUE : FALSE;
|
factory)) ? TRUE : FALSE;
|
||||||
#endif
|
#endif
|
||||||
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory) );
|
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory));
|
||||||
|
|
||||||
iswic2 = g_WIC2;
|
iswic2 = g_WIC2;
|
||||||
return g_Factory;
|
return g_Factory;
|
||||||
@ -290,7 +290,7 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
|
|||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Optional initializer for WIC factory
|
// Optional initializer for WIC factory
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
void DirectX::SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
||||||
{
|
{
|
||||||
if (pWIC == g_Factory)
|
if (pWIC == g_Factory)
|
||||||
return;
|
return;
|
||||||
@ -311,7 +311,7 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
|||||||
|
|
||||||
g_WIC2 = iswic2;
|
g_WIC2 = iswic2;
|
||||||
std::swap(pWIC, g_Factory);
|
std::swap(pWIC, g_Factory);
|
||||||
if ( pWIC )
|
if (pWIC)
|
||||||
pWIC->Release();
|
pWIC->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,9 +323,9 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_R8G8_B8G8_UNORM:
|
||||||
case DXGI_FORMAT_G8R8_G8B8_UNORM:
|
case DXGI_FORMAT_G8R8_G8B8_UNORM:
|
||||||
@ -342,9 +342,9 @@ bool IsPacked(DXGI_FORMAT fmt)
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_AYUV:
|
||||||
case DXGI_FORMAT_Y410:
|
case DXGI_FORMAT_Y410:
|
||||||
@ -379,9 +379,9 @@ bool IsVideo(DXGI_FORMAT fmt)
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_NV12: // 4:2:0 8-bit
|
||||||
case DXGI_FORMAT_P010: // 4:2:0 10-bit
|
case DXGI_FORMAT_P010: // 4:2:0 10-bit
|
||||||
@ -403,15 +403,14 @@ bool IsPlanar(DXGI_FORMAT fmt)
|
|||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_D32_FLOAT_S8X24_UINT:
|
||||||
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
||||||
@ -434,9 +433,9 @@ bool IsDepthStencil(DXGI_FORMAT fmt)
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_R32G32B32A32_TYPELESS:
|
||||||
case DXGI_FORMAT_R32G32B32_TYPELESS:
|
case DXGI_FORMAT_R32G32B32_TYPELESS:
|
||||||
@ -478,9 +477,9 @@ bool IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_TYPELESS:
|
||||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
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
|
// Returns bits-per-pixel for a given DXGI format, or 0 on failure
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_TYPELESS:
|
||||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
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
|
// For mixed formats, it returns the largest color-depth in the format
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_TYPELESS:
|
||||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||||
@ -869,10 +868,10 @@ size_t BitsPerColor( DXGI_FORMAT fmt )
|
|||||||
// based on DXGI format, width, and height
|
// based on DXGI format, width, and height
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||||
size_t& rowPitch, size_t& slicePitch, DWORD flags )
|
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_TYPELESS:
|
||||||
case DXGI_FORMAT_BC1_UNORM:
|
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:
|
case DXGI_FORMAT_BC4_SNORM:
|
||||||
assert(IsCompressed(fmt));
|
assert(IsCompressed(fmt));
|
||||||
{
|
{
|
||||||
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
|
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||||
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
|
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||||
rowPitch = nbw * 8;
|
rowPitch = nbw * 8;
|
||||||
|
|
||||||
slicePitch = rowPitch * nbh;
|
slicePitch = rowPitch * nbh;
|
||||||
@ -907,8 +906,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
|||||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||||
assert(IsCompressed(fmt));
|
assert(IsCompressed(fmt));
|
||||||
{
|
{
|
||||||
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
|
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||||
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
|
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||||
rowPitch = nbw * 16;
|
rowPitch = nbw * 16;
|
||||||
|
|
||||||
slicePitch = rowPitch * nbh;
|
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_G8R8_G8B8_UNORM:
|
||||||
case DXGI_FORMAT_YUY2:
|
case DXGI_FORMAT_YUY2:
|
||||||
assert(IsPacked(fmt));
|
assert(IsPacked(fmt));
|
||||||
rowPitch = ( ( width + 1 ) >> 1 ) * 4;
|
rowPitch = ((width + 1) >> 1) * 4;
|
||||||
slicePitch = rowPitch * height;
|
slicePitch = rowPitch * height;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DXGI_FORMAT_Y210:
|
case DXGI_FORMAT_Y210:
|
||||||
case DXGI_FORMAT_Y216:
|
case DXGI_FORMAT_Y216:
|
||||||
assert(IsPacked(fmt));
|
assert(IsPacked(fmt));
|
||||||
rowPitch = ( ( width + 1 ) >> 1 ) * 8;
|
rowPitch = ((width + 1) >> 1) * 8;
|
||||||
slicePitch = rowPitch * height;
|
slicePitch = rowPitch * height;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DXGI_FORMAT_NV12:
|
case DXGI_FORMAT_NV12:
|
||||||
case DXGI_FORMAT_420_OPAQUE:
|
case DXGI_FORMAT_420_OPAQUE:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
rowPitch = ( ( width + 1 ) >> 1 ) * 2;
|
rowPitch = ((width + 1) >> 1) * 2;
|
||||||
slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
|
slicePitch = rowPitch * (height + ((height + 1) >> 1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DXGI_FORMAT_P010:
|
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_R16_UNORM_X8_TYPELESS:
|
||||||
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
rowPitch = ( ( width + 1 ) >> 1 ) * 4;
|
rowPitch = ((width + 1) >> 1) * 4;
|
||||||
slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
|
slicePitch = rowPitch * (height + ((height + 1) >> 1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DXGI_FORMAT_NV11:
|
case DXGI_FORMAT_NV11:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
rowPitch = ( ( width + 3 ) >> 2 ) * 4;
|
rowPitch = ((width + 3) >> 2) * 4;
|
||||||
slicePitch = rowPitch * height * 2;
|
slicePitch = rowPitch * height * 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIN10_DXGI_FORMAT_P208:
|
case WIN10_DXGI_FORMAT_P208:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
rowPitch = ( ( width + 1 ) >> 1 ) * 2;
|
rowPitch = ((width + 1) >> 1) * 2;
|
||||||
slicePitch = rowPitch * height * 2;
|
slicePitch = rowPitch * height * 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIN10_DXGI_FORMAT_V208:
|
case WIN10_DXGI_FORMAT_V208:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
rowPitch = width;
|
rowPitch = width;
|
||||||
slicePitch = rowPitch * ( height + ( ( ( height + 1 ) >> 1 ) * 2 ) );
|
slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WIN10_DXGI_FORMAT_V408:
|
case WIN10_DXGI_FORMAT_V408:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
rowPitch = width;
|
rowPitch = width;
|
||||||
slicePitch = rowPitch * ( height + ( ( height >> 1 ) * 4 ) );
|
slicePitch = rowPitch * (height + ((height >> 1) * 4));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert( IsValid(fmt) );
|
assert(IsValid(fmt));
|
||||||
assert( !IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt) );
|
assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt));
|
||||||
{
|
{
|
||||||
|
|
||||||
size_t bpp;
|
size_t bpp;
|
||||||
|
|
||||||
if ( flags & CP_FLAGS_24BPP )
|
if (flags & CP_FLAGS_24BPP)
|
||||||
bpp = 24;
|
bpp = 24;
|
||||||
else if ( flags & CP_FLAGS_16BPP )
|
else if (flags & CP_FLAGS_16BPP)
|
||||||
bpp = 16;
|
bpp = 16;
|
||||||
else if ( flags & CP_FLAGS_8BPP )
|
else if (flags & CP_FLAGS_8BPP)
|
||||||
bpp = 8;
|
bpp = 8;
|
||||||
else
|
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;
|
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;
|
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;
|
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;
|
slicePitch = rowPitch * height;
|
||||||
}
|
}
|
||||||
else // DWORD alignment
|
else // DWORD alignment
|
||||||
{
|
{
|
||||||
// Special computation for some incorrectly created DDS files based on
|
// Special computation for some incorrectly created DDS files based on
|
||||||
// legacy DirectDraw assumptions about pitch alignment
|
// 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;
|
slicePitch = rowPitch * height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Default byte alignment
|
// Default byte alignment
|
||||||
rowPitch = ( width * bpp + 7 ) / 8;
|
rowPitch = (width * bpp + 7) / 8;
|
||||||
slicePitch = rowPitch * height;
|
slicePitch = rowPitch * height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1031,9 +1030,9 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_TYPELESS:
|
||||||
case DXGI_FORMAT_BC1_UNORM:
|
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:
|
||||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||||
assert(IsCompressed(fmt));
|
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 DXGI_FORMAT_NV11:
|
||||||
case WIN10_DXGI_FORMAT_P208:
|
case WIN10_DXGI_FORMAT_P208:
|
||||||
@ -1066,11 +1065,11 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
|||||||
|
|
||||||
case WIN10_DXGI_FORMAT_V208:
|
case WIN10_DXGI_FORMAT_V208:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
return height + ( ( (height + 1) >> 1 ) * 2 );
|
return height + (((height + 1) >> 1) * 2);
|
||||||
|
|
||||||
case WIN10_DXGI_FORMAT_V408:
|
case WIN10_DXGI_FORMAT_V408:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
return height + ( (height >> 1) * 4 );
|
return height + ((height >> 1) * 4);
|
||||||
|
|
||||||
case DXGI_FORMAT_NV12:
|
case DXGI_FORMAT_NV12:
|
||||||
case DXGI_FORMAT_P010:
|
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_R16_UNORM_X8_TYPELESS:
|
||||||
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
||||||
assert(IsPlanar(fmt));
|
assert(IsPlanar(fmt));
|
||||||
return height + ( ( height + 1 ) >> 1 );
|
return height + ((height + 1) >> 1);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert( IsValid(fmt) );
|
assert(IsValid(fmt));
|
||||||
assert( !IsCompressed(fmt) && !IsPlanar(fmt) );
|
assert(!IsCompressed(fmt) && !IsPlanar(fmt));
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1094,9 +1093,9 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
|||||||
// Converts to an SRGB equivalent type if available
|
// Converts to an SRGB equivalent type if available
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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:
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
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
|
// Converts to a format to an equivalent TYPELESS format if available
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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_FLOAT:
|
||||||
case DXGI_FORMAT_R32G32B32A32_UINT:
|
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
|
// Converts to a TYPELESS format to an equivalent UNORM format if available
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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:
|
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
|
||||||
return DXGI_FORMAT_R16G16B16A16_UNORM;
|
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
|
// Converts to a TYPELESS format to an equivalent FLOAT format if available
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
_Use_decl_annotations_
|
_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:
|
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||||
@ -1344,25 +1343,25 @@ DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
|
|||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_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);
|
return size_t(-1);
|
||||||
|
|
||||||
switch( dimension )
|
switch (dimension)
|
||||||
{
|
{
|
||||||
case TEX_DIMENSION_TEXTURE1D:
|
case TEX_DIMENSION_TEXTURE1D:
|
||||||
case TEX_DIMENSION_TEXTURE2D:
|
case TEX_DIMENSION_TEXTURE2D:
|
||||||
if ( slice > 0 )
|
if (slice > 0)
|
||||||
return size_t(-1);
|
return size_t(-1);
|
||||||
|
|
||||||
if ( item >= arraySize )
|
if (item >= arraySize)
|
||||||
return size_t(-1);
|
return size_t(-1);
|
||||||
|
|
||||||
return (item*( mipLevels ) + mip);
|
return (item*(mipLevels)+mip);
|
||||||
|
|
||||||
case TEX_DIMENSION_TEXTURE3D:
|
case TEX_DIMENSION_TEXTURE3D:
|
||||||
if ( item > 0 )
|
if (item > 0)
|
||||||
{
|
{
|
||||||
// No support for arrays of volumes
|
// No support for arrays of volumes
|
||||||
return size_t(-1);
|
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 index = 0;
|
||||||
size_t d = depth;
|
size_t d = depth;
|
||||||
|
|
||||||
for( size_t level = 0; level < mip; ++level )
|
for (size_t level = 0; level < mip; ++level)
|
||||||
{
|
{
|
||||||
index += d;
|
index += d;
|
||||||
if ( d > 1 )
|
if (d > 1)
|
||||||
d >>= 1;
|
d >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( slice >= d )
|
if (slice >= d)
|
||||||
return size_t(-1);
|
return size_t(-1);
|
||||||
|
|
||||||
index += slice;
|
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)
|
Blob& Blob::operator= (Blob&& moveFrom)
|
||||||
{
|
{
|
||||||
if ( this != &moveFrom )
|
if (this != &moveFrom)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
|
|
||||||
_buffer = moveFrom._buffer;
|
m_buffer = moveFrom.m_buffer;
|
||||||
_size = moveFrom._size;
|
m_size = moveFrom.m_size;
|
||||||
|
|
||||||
moveFrom._buffer = nullptr;
|
moveFrom.m_buffer = nullptr;
|
||||||
moveFrom._size = 0;
|
moveFrom.m_size = 0;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blob::Release()
|
void Blob::Release()
|
||||||
{
|
{
|
||||||
if ( _buffer )
|
if (m_buffer)
|
||||||
{
|
{
|
||||||
_aligned_free( _buffer );
|
_aligned_free(m_buffer);
|
||||||
_buffer = nullptr;
|
m_buffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
_size = 0;
|
m_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Use_decl_annotations_
|
_Use_decl_annotations_
|
||||||
HRESULT Blob::Initialize( size_t size )
|
HRESULT Blob::Initialize(size_t size)
|
||||||
{
|
{
|
||||||
if ( !size )
|
if (!size)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
Release();
|
Release();
|
||||||
|
|
||||||
_buffer = _aligned_malloc( size, 16 );
|
m_buffer = _aligned_malloc(size, 16);
|
||||||
if ( !_buffer )
|
if (!m_buffer)
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
_size = size;
|
m_size = size;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -63,36 +63,36 @@ struct LinearFilter
|
|||||||
float weight1;
|
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(source > 0);
|
||||||
assert( dest > 0 );
|
assert(dest > 0);
|
||||||
assert( lf != 0 );
|
assert(lf != 0);
|
||||||
|
|
||||||
float scale = float(source) / float(dest);
|
float scale = float(source) / float(dest);
|
||||||
|
|
||||||
// Mirror is the same case as clamp for linear
|
// 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 isrcB = ptrdiff_t(srcB);
|
||||||
ptrdiff_t isrcA = isrcB - 1;
|
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;
|
float weight = 1.0f + float(isrcB) - srcB;
|
||||||
|
|
||||||
auto& entry = lf[ u ];
|
auto& entry = lf[u];
|
||||||
entry.u0 = size_t(isrcA);
|
entry.u0 = size_t(isrcA);
|
||||||
entry.weight0 = weight;
|
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_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 };
|
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;
|
u = maxu + u + 1;
|
||||||
}
|
}
|
||||||
else if ( u > maxu )
|
else if (u > maxu)
|
||||||
{
|
{
|
||||||
u = u - maxu - 1;
|
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);
|
u = maxu - (u - maxu - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles clamp, but also a safety factor for degenerate images for wrap/mirror
|
// Handles clamp, but also a safety factor for degenerate images for wrap/mirror
|
||||||
u = std::min<ptrdiff_t>( u, maxu );
|
u = std::min<ptrdiff_t>(u, maxu);
|
||||||
u = std::max<ptrdiff_t>( u, 0 );
|
u = std::max<ptrdiff_t>(u, 0);
|
||||||
|
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
@ -161,24 +161,24 @@ struct CubicFilter
|
|||||||
float x;
|
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(source > 0);
|
||||||
assert( dest > 0 );
|
assert(dest > 0);
|
||||||
assert( cf != 0 );
|
assert(cf != 0);
|
||||||
|
|
||||||
float scale = float(source) / float(dest);
|
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 isrcB = bounduvw(ptrdiff_t(srcB), source - 1, wrap, mirror);
|
||||||
ptrdiff_t isrcA = bounduvw( isrcB - 1, 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 isrcC = bounduvw(isrcB + 1, source - 1, wrap, mirror);
|
||||||
ptrdiff_t isrcD = bounduvw( isrcB + 2, 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.u0 = size_t(isrcA);
|
||||||
entry.u1 = size_t(isrcB);
|
entry.u1 = size_t(isrcB);
|
||||||
entry.u2 = size_t(isrcC);
|
entry.u2 = size_t(isrcC);
|
||||||
@ -246,10 +246,10 @@ namespace TriangleFilter
|
|||||||
|
|
||||||
static const float TF_EPSILON = 0.00001f;
|
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(source > 0);
|
||||||
assert( dest > 0 );
|
assert(dest > 0);
|
||||||
|
|
||||||
float scale = float(dest) / float(source);
|
float scale = float(dest) / float(source);
|
||||||
float scaleInv = 0.5f / scale;
|
float scaleInv = 0.5f / scale;
|
||||||
@ -258,109 +258,109 @@ namespace TriangleFilter
|
|||||||
size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE;
|
size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE;
|
||||||
float repeat = (wrap) ? 1.f : 0.f;
|
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 src = float(u) - 0.5f;
|
||||||
float destMin = src * scale;
|
float destMin = src * scale;
|
||||||
float destMax = destMin + 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;
|
uint8_t* pFilter = nullptr;
|
||||||
|
|
||||||
if ( tf )
|
if (tf)
|
||||||
{
|
{
|
||||||
// See if existing filter memory block is large enough to reuse
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// Need to reallocate filter memory block
|
// Need to reallocate filter memory block
|
||||||
tf.reset( nullptr );
|
tf.reset(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !tf )
|
if (!tf)
|
||||||
{
|
{
|
||||||
// Allocate filter memory block
|
// Allocate filter memory block
|
||||||
pFilter = new (std::nothrow) uint8_t[ totalSize ];
|
pFilter = new (std::nothrow) uint8_t[totalSize];
|
||||||
if ( !pFilter )
|
if (!pFilter)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
tf.reset( reinterpret_cast<Filter*>( pFilter ) );
|
tf.reset(reinterpret_cast<Filter*>(pFilter));
|
||||||
tf->totalSize = totalSize;
|
tf->totalSize = totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( pFilter != 0 );
|
assert(pFilter != 0);
|
||||||
|
|
||||||
// Filter setup
|
// Filter setup
|
||||||
size_t sizeInBytes = TF_FILTER_SIZE;
|
size_t sizeInBytes = TF_FILTER_SIZE;
|
||||||
size_t accumU = 0;
|
size_t accumU = 0;
|
||||||
float accumWeight = 0.f;
|
float accumWeight = 0.f;
|
||||||
|
|
||||||
for( size_t u = 0; u < source; ++u )
|
for (size_t u = 0; u < source; ++u)
|
||||||
{
|
{
|
||||||
// Setup from entry
|
// Setup from entry
|
||||||
size_t sizeFrom = sizeInBytes;
|
size_t sizeFrom = sizeInBytes;
|
||||||
auto pFrom = reinterpret_cast<FilterFrom*>( pFilter + sizeInBytes );
|
auto pFrom = reinterpret_cast<FilterFrom*>(pFilter + sizeInBytes);
|
||||||
sizeInBytes += TF_FROM_SIZE;
|
sizeInBytes += TF_FROM_SIZE;
|
||||||
|
|
||||||
if ( sizeInBytes > totalSize )
|
if (sizeInBytes > totalSize)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
size_t toCount = 0;
|
size_t toCount = 0;
|
||||||
|
|
||||||
// Perform two passes to capture the influences from both sides
|
// 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 destMin = src * scale;
|
||||||
float destMax = destMin + scale;
|
float destMax = destMin + scale;
|
||||||
|
|
||||||
if ( !wrap )
|
if (!wrap)
|
||||||
{
|
{
|
||||||
// Clamp
|
// Clamp
|
||||||
if ( destMin < 0.f )
|
if (destMin < 0.f)
|
||||||
destMin = 0.f;
|
destMin = 0.f;
|
||||||
if ( destMax > float(dest) )
|
if (destMax > float(dest))
|
||||||
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 d0 = float(k);
|
||||||
float d1 = d0 + 1.f;
|
float d1 = d0 + 1.f;
|
||||||
|
|
||||||
size_t u0;
|
size_t u0;
|
||||||
if ( k < 0 )
|
if (k < 0)
|
||||||
{
|
{
|
||||||
// Handle wrap
|
// 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
|
// Handle wrap
|
||||||
u0 = size_t( k - ptrdiff_t(dest) );
|
u0 = size_t(k - ptrdiff_t(dest));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u0 = size_t( k );
|
u0 = size_t(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save previous accumulated weight (if any)
|
// 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;
|
sizeInBytes += TF_TO_SIZE;
|
||||||
++toCount;
|
++toCount;
|
||||||
|
|
||||||
if ( sizeInBytes > totalSize )
|
if (sizeInBytes > totalSize)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
pTo->u = accumU;
|
pTo->u = accumU;
|
||||||
@ -372,33 +372,33 @@ namespace TriangleFilter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clip destination
|
// Clip destination
|
||||||
if ( d0 < destMin )
|
if (d0 < destMin)
|
||||||
d0 = destMin;
|
d0 = destMin;
|
||||||
if ( d1 > destMax )
|
if (d1 > destMax)
|
||||||
d1 = destMax;
|
d1 = destMax;
|
||||||
|
|
||||||
// Calculate average weight over destination pixel
|
// Calculate average weight over destination pixel
|
||||||
|
|
||||||
float weight;
|
float weight;
|
||||||
if ( !wrap && src < 0.f )
|
if (!wrap && src < 0.f)
|
||||||
weight = 1.f;
|
weight = 1.f;
|
||||||
else if ( !wrap && ( ( src + 1.f ) >= float(source) ) )
|
else if (!wrap && ((src + 1.f) >= float(source)))
|
||||||
weight = 0.f;
|
weight = 0.f;
|
||||||
else
|
else
|
||||||
weight = (d0 + d1) * scaleInv - src;
|
weight = (d0 + d1) * scaleInv - src;
|
||||||
|
|
||||||
accumWeight += (d1 - d0) * ( j ? (1.f - weight) : weight );
|
accumWeight += (d1 - d0) * (j ? (1.f - weight) : weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store accumulated 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;
|
sizeInBytes += TF_TO_SIZE;
|
||||||
++toCount;
|
++toCount;
|
||||||
|
|
||||||
if ( sizeInBytes > totalSize )
|
if (sizeInBytes > totalSize)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
pTo->u = accumU;
|
pTo->u = accumU;
|
||||||
@ -417,6 +417,6 @@ namespace TriangleFilter
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace
|
}; // namespace TriangleFilter
|
||||||
|
|
||||||
}; // namespace
|
}; // namespace DirectX
|
@ -229,7 +229,7 @@ namespace
|
|||||||
class auto_delete_file_wic
|
class auto_delete_file_wic
|
||||||
{
|
{
|
||||||
public:
|
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()
|
~auto_delete_file_wic()
|
||||||
{
|
{
|
||||||
if (m_filename)
|
if (m_filename)
|
||||||
@ -242,7 +242,7 @@ namespace
|
|||||||
void clear() { m_filename = 0; }
|
void clear() { m_filename = 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LPCWSTR m_filename;
|
const wchar_t* m_filename;
|
||||||
ComPtr<IWICStream>& m_handle;
|
ComPtr<IWICStream>& m_handle;
|
||||||
|
|
||||||
auto_delete_file_wic(const auto_delete_file_wic&) = delete;
|
auto_delete_file_wic(const auto_delete_file_wic&) = delete;
|
||||||
@ -705,7 +705,7 @@ namespace
|
|||||||
|
|
||||||
IWICImagingFactory* factory = nullptr;
|
IWICImagingFactory* factory = nullptr;
|
||||||
InitOnceExecuteOnce(&s_initOnce,
|
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(
|
HRESULT hr = CoCreateInstance(
|
||||||
@ -751,7 +751,7 @@ namespace
|
|||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||||
_In_ ID3D11Resource* pSource,
|
_In_ ID3D11Resource* pSource,
|
||||||
_In_z_ LPCWSTR fileName )
|
_In_z_ const wchar_t* fileName )
|
||||||
{
|
{
|
||||||
if ( !fileName )
|
if ( !fileName )
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
@ -764,9 +764,9 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
|||||||
|
|
||||||
// Create file
|
// Create file
|
||||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
#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
|
#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
|
#endif
|
||||||
if ( !hFile )
|
if ( !hFile )
|
||||||
return HRESULT_FROM_WIN32( GetLastError() );
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||||||
@ -912,7 +912,7 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
|||||||
HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||||
_In_ ID3D11Resource* pSource,
|
_In_ ID3D11Resource* pSource,
|
||||||
_In_ REFGUID guidContainerFormat,
|
_In_ REFGUID guidContainerFormat,
|
||||||
_In_z_ LPCWSTR fileName,
|
_In_z_ const wchar_t* fileName,
|
||||||
_In_opt_ const GUID* targetFormat,
|
_In_opt_ const GUID* targetFormat,
|
||||||
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps )
|
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps )
|
||||||
{
|
{
|
||||||
|
@ -32,12 +32,12 @@ namespace DirectX
|
|||||||
{
|
{
|
||||||
HRESULT SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
HRESULT SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||||
_In_ ID3D11Resource* pSource,
|
_In_ ID3D11Resource* pSource,
|
||||||
_In_z_ LPCWSTR fileName );
|
_In_z_ const wchar_t* fileName );
|
||||||
|
|
||||||
HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||||
_In_ ID3D11Resource* pSource,
|
_In_ ID3D11Resource* pSource,
|
||||||
_In_ REFGUID guidContainerFormat,
|
_In_ REFGUID guidContainerFormat,
|
||||||
_In_z_ LPCWSTR fileName,
|
_In_z_ const wchar_t* fileName,
|
||||||
_In_opt_ const GUID* targetFormat = nullptr,
|
_In_opt_ const GUID* targetFormat = nullptr,
|
||||||
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps = nullptr );
|
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps = nullptr );
|
||||||
}
|
}
|
@ -839,11 +839,7 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
|
|||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
// Create file
|
// Create file
|
||||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, nullptr ) ) );
|
||||||
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
|
|
||||||
if ( !hFile )
|
if ( !hFile )
|
||||||
return HRESULT_FROM_WIN32( GetLastError() );
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||||||
|
|
||||||
@ -972,13 +968,13 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
|
|||||||
|
|
||||||
// Write header & pixels
|
// Write header & pixels
|
||||||
DWORD bytesWritten;
|
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() );
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||||||
|
|
||||||
if ( bytesWritten != headerSize )
|
if ( bytesWritten != headerSize )
|
||||||
return E_FAIL;
|
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() );
|
return HRESULT_FROM_WIN32( GetLastError() );
|
||||||
|
|
||||||
if ( bytesWritten != slicePitch )
|
if ( bytesWritten != slicePitch )
|
||||||
|
@ -34,7 +34,8 @@
|
|||||||
namespace DirectX
|
namespace DirectX
|
||||||
{
|
{
|
||||||
// Standard version
|
// Standard version
|
||||||
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromMemory(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||||
_In_ size_t wicDataSize,
|
_In_ size_t wicDataSize,
|
||||||
_Out_opt_ ID3D11Resource** texture,
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
@ -42,7 +43,8 @@ namespace DirectX
|
|||||||
_In_ size_t maxsize = 0
|
_In_ size_t maxsize = 0
|
||||||
);
|
);
|
||||||
|
|
||||||
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromFile(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_z_ const wchar_t* szFileName,
|
_In_z_ const wchar_t* szFileName,
|
||||||
_Out_opt_ ID3D11Resource** texture,
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||||
@ -50,7 +52,8 @@ namespace DirectX
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Standard version with optional auto-gen mipmap support
|
// Standard version with optional auto-gen mipmap support
|
||||||
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromMemory(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||||
_In_ size_t wicDataSize,
|
_In_ size_t wicDataSize,
|
||||||
@ -59,7 +62,8 @@ namespace DirectX
|
|||||||
_In_ size_t maxsize = 0
|
_In_ size_t maxsize = 0
|
||||||
);
|
);
|
||||||
|
|
||||||
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromFile(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
_In_z_ const wchar_t* szFileName,
|
_In_z_ const wchar_t* szFileName,
|
||||||
_Out_opt_ ID3D11Resource** texture,
|
_Out_opt_ ID3D11Resource** texture,
|
||||||
@ -68,11 +72,12 @@ namespace DirectX
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Extended version
|
// Extended version
|
||||||
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromMemoryEx(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||||
_In_ size_t wicDataSize,
|
_In_ size_t wicDataSize,
|
||||||
_In_ size_t maxsize,
|
_In_ size_t maxsize,
|
||||||
_In_ D3D11_USAGE usage,
|
D3D11_USAGE usage,
|
||||||
_In_ unsigned int bindFlags,
|
_In_ unsigned int bindFlags,
|
||||||
_In_ unsigned int cpuAccessFlags,
|
_In_ unsigned int cpuAccessFlags,
|
||||||
_In_ unsigned int miscFlags,
|
_In_ unsigned int miscFlags,
|
||||||
@ -81,7 +86,8 @@ namespace DirectX
|
|||||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||||
);
|
);
|
||||||
|
|
||||||
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromFileEx(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_z_ const wchar_t* szFileName,
|
_In_z_ const wchar_t* szFileName,
|
||||||
_In_ size_t maxsize,
|
_In_ size_t maxsize,
|
||||||
_In_ D3D11_USAGE usage,
|
_In_ D3D11_USAGE usage,
|
||||||
@ -94,7 +100,8 @@ namespace DirectX
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Extended version with optional auto-gen mipmap support
|
// Extended version with optional auto-gen mipmap support
|
||||||
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromMemoryEx(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||||
_In_ size_t wicDataSize,
|
_In_ size_t wicDataSize,
|
||||||
@ -108,7 +115,8 @@ namespace DirectX
|
|||||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||||
);
|
);
|
||||||
|
|
||||||
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
|
HRESULT CreateWICTextureFromFileEx(
|
||||||
|
_In_ ID3D11Device* d3dDevice,
|
||||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||||
_In_z_ const wchar_t* szFileName,
|
_In_z_ const wchar_t* szFileName,
|
||||||
_In_ size_t maxsize,
|
_In_ size_t maxsize,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user