mirror of
https://github.com/microsoft/DirectXTex
synced 2024-11-21 20:10:05 +00:00
General code cleanuP
This commit is contained in:
parent
53e66ba1e9
commit
51bc3d5b16
@ -165,21 +165,11 @@ namespace
|
||||
}
|
||||
|
||||
// open the file
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
||||
ScopedHandle hFile( safe_handle( CreateFile2( fileName,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
OPEN_EXISTING,
|
||||
nullptr ) ) );
|
||||
#else
|
||||
ScopedHandle hFile( safe_handle( CreateFileW( fileName,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr ) ) );
|
||||
#endif
|
||||
|
||||
if ( !hFile )
|
||||
{
|
||||
|
1373
DirectXTex/BC.cpp
1373
DirectXTex/BC.cpp
File diff suppressed because it is too large
Load Diff
@ -17,8 +17,7 @@
|
||||
|
||||
#include "BC.h"
|
||||
|
||||
namespace DirectX
|
||||
{
|
||||
using namespace DirectX;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Constants
|
||||
@ -26,338 +25,361 @@ namespace DirectX
|
||||
|
||||
// Because these are used in SAL annotations, they need to remain macros rather than const values
|
||||
#define BLOCK_LEN 4
|
||||
// length of each block in texel
|
||||
// length of each block in texel
|
||||
|
||||
#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN)
|
||||
// total texels in a 4x4 block.
|
||||
// total texels in a 4x4 block.
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Structures
|
||||
//-------------------------------------------------------------------------------------
|
||||
namespace
|
||||
{
|
||||
//------------------------------------------------------------------------------------
|
||||
// Structures
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
|
||||
// BC4U/BC5U
|
||||
struct BC4_UNORM
|
||||
{
|
||||
float R(size_t uOffset) const
|
||||
// BC4U/BC5U
|
||||
struct BC4_UNORM
|
||||
{
|
||||
size_t uIndex = GetIndex(uOffset);
|
||||
return DecodeFromIndex(uIndex);
|
||||
}
|
||||
|
||||
float DecodeFromIndex(size_t uIndex) const
|
||||
{
|
||||
if (uIndex == 0)
|
||||
return red_0 / 255.0f;
|
||||
if (uIndex == 1)
|
||||
return red_1 / 255.0f;
|
||||
float fred_0 = red_0 / 255.0f;
|
||||
float fred_1 = red_1 / 255.0f;
|
||||
if (red_0 > red_1)
|
||||
float R(size_t uOffset) const
|
||||
{
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
|
||||
size_t uIndex = GetIndex(uOffset);
|
||||
return DecodeFromIndex(uIndex);
|
||||
}
|
||||
else
|
||||
|
||||
float DecodeFromIndex(size_t uIndex) const
|
||||
{
|
||||
if (uIndex == 6)
|
||||
return 0.0f;
|
||||
if (uIndex == 7)
|
||||
return 1.0f;
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
|
||||
if (uIndex == 0)
|
||||
return red_0 / 255.0f;
|
||||
if (uIndex == 1)
|
||||
return red_1 / 255.0f;
|
||||
float fred_0 = red_0 / 255.0f;
|
||||
float fred_1 = red_1 / 255.0f;
|
||||
if (red_0 > red_1)
|
||||
{
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uIndex == 6)
|
||||
return 0.0f;
|
||||
if (uIndex == 7)
|
||||
return 1.0f;
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetIndex(size_t uOffset) const
|
||||
{
|
||||
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
|
||||
}
|
||||
|
||||
void SetIndex(size_t uOffset, size_t uIndex)
|
||||
{
|
||||
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
|
||||
data |= ((uint64_t) uIndex << (3*uOffset + 16));
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
size_t GetIndex(size_t uOffset) const
|
||||
{
|
||||
uint8_t red_0;
|
||||
uint8_t red_1;
|
||||
uint8_t indices[6];
|
||||
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
|
||||
}
|
||||
|
||||
void SetIndex(size_t uOffset, size_t uIndex)
|
||||
{
|
||||
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
|
||||
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t red_0;
|
||||
uint8_t red_1;
|
||||
uint8_t indices[6];
|
||||
};
|
||||
uint64_t data;
|
||||
};
|
||||
uint64_t data;
|
||||
};
|
||||
};
|
||||
|
||||
// BC4S/BC5S
|
||||
struct BC4_SNORM
|
||||
{
|
||||
float R(size_t uOffset) const
|
||||
// BC4S/BC5S
|
||||
struct BC4_SNORM
|
||||
{
|
||||
size_t uIndex = GetIndex(uOffset);
|
||||
return DecodeFromIndex(uIndex);
|
||||
}
|
||||
|
||||
float DecodeFromIndex(size_t uIndex) const
|
||||
{
|
||||
int8_t sred_0 = (red_0 == -128)? -127 : red_0;
|
||||
int8_t sred_1 = (red_1 == -128)? -127 : red_1;
|
||||
|
||||
if (uIndex == 0)
|
||||
return sred_0 / 127.0f;
|
||||
if (uIndex == 1)
|
||||
return sred_1 / 127.0f;
|
||||
float fred_0 = sred_0 / 127.0f;
|
||||
float fred_1 = sred_1 / 127.0f;
|
||||
if (red_0 > red_1)
|
||||
float R(size_t uOffset) const
|
||||
{
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
|
||||
size_t uIndex = GetIndex(uOffset);
|
||||
return DecodeFromIndex(uIndex);
|
||||
}
|
||||
else
|
||||
|
||||
float DecodeFromIndex(size_t uIndex) const
|
||||
{
|
||||
if (uIndex == 6)
|
||||
return -1.0f;
|
||||
if (uIndex == 7)
|
||||
return 1.0f;
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
|
||||
int8_t sred_0 = (red_0 == -128) ? -127 : red_0;
|
||||
int8_t sred_1 = (red_1 == -128) ? -127 : red_1;
|
||||
|
||||
if (uIndex == 0)
|
||||
return sred_0 / 127.0f;
|
||||
if (uIndex == 1)
|
||||
return sred_1 / 127.0f;
|
||||
float fred_0 = sred_0 / 127.0f;
|
||||
float fred_1 = sred_1 / 127.0f;
|
||||
if (red_0 > red_1)
|
||||
{
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uIndex == 6)
|
||||
return -1.0f;
|
||||
if (uIndex == 7)
|
||||
return 1.0f;
|
||||
uIndex -= 1;
|
||||
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetIndex(size_t uOffset) const
|
||||
{
|
||||
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
|
||||
}
|
||||
|
||||
void SetIndex(size_t uOffset, size_t uIndex)
|
||||
{
|
||||
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
|
||||
data |= ((uint64_t) uIndex << (3*uOffset + 16));
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
size_t GetIndex(size_t uOffset) const
|
||||
{
|
||||
int8_t red_0;
|
||||
int8_t red_1;
|
||||
uint8_t indices[6];
|
||||
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
|
||||
}
|
||||
|
||||
void SetIndex(size_t uOffset, size_t uIndex)
|
||||
{
|
||||
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
|
||||
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int8_t red_0;
|
||||
int8_t red_1;
|
||||
uint8_t indices[6];
|
||||
};
|
||||
uint64_t data;
|
||||
};
|
||||
uint64_t data;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Convert a floating point value to an 8-bit SNORM
|
||||
//-------------------------------------------------------------------------------------
|
||||
static void inline FloatToSNorm( _In_ float fVal, _Out_ int8_t *piSNorm )
|
||||
{
|
||||
const uint32_t dwMostNeg = ( 1 << ( 8 * sizeof( int8_t ) - 1 ) );
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Convert a floating point value to an 8-bit SNORM
|
||||
//-------------------------------------------------------------------------------------
|
||||
void inline FloatToSNorm(_In_ float fVal, _Out_ int8_t *piSNorm)
|
||||
{
|
||||
const uint32_t dwMostNeg = (1 << (8 * sizeof(int8_t) - 1));
|
||||
|
||||
if( _isnan( fVal ) )
|
||||
fVal = 0;
|
||||
else
|
||||
if( fVal > 1 )
|
||||
fVal = 1; // Clamp to 1
|
||||
if (_isnan(fVal))
|
||||
fVal = 0;
|
||||
else
|
||||
if( fVal < -1 )
|
||||
fVal = -1; // Clamp to -1
|
||||
if (fVal > 1)
|
||||
fVal = 1; // Clamp to 1
|
||||
else
|
||||
if (fVal < -1)
|
||||
fVal = -1; // Clamp to -1
|
||||
|
||||
fVal = fVal * (int8_t) ( dwMostNeg - 1 );
|
||||
fVal = fVal * (int8_t)(dwMostNeg - 1);
|
||||
|
||||
if( fVal >= 0 )
|
||||
fVal += .5f;
|
||||
else
|
||||
fVal -= .5f;
|
||||
if (fVal >= 0)
|
||||
fVal += .5f;
|
||||
else
|
||||
fVal -= .5f;
|
||||
|
||||
*piSNorm = (int8_t) (fVal);
|
||||
}
|
||||
*piSNorm = (int8_t)(fVal);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1)
|
||||
{
|
||||
// The boundary of codec for signed/unsigned format
|
||||
float MIN_NORM;
|
||||
float MAX_NORM = 1.0f;
|
||||
int8_t iStart, iEnd;
|
||||
size_t i;
|
||||
|
||||
MIN_NORM = 0.0f;
|
||||
|
||||
// Find max/min of input texels
|
||||
float fBlockMax = theTexelsU[0];
|
||||
float fBlockMin = theTexelsU[0];
|
||||
for (i = 0; i < BLOCK_SIZE; ++i)
|
||||
//------------------------------------------------------------------------------
|
||||
void FindEndPointsBC4U(
|
||||
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
|
||||
_Out_ uint8_t &endpointU_0,
|
||||
_Out_ uint8_t &endpointU_1)
|
||||
{
|
||||
if (theTexelsU[i]<fBlockMin)
|
||||
// The boundary of codec for signed/unsigned format
|
||||
float MIN_NORM;
|
||||
float MAX_NORM = 1.0f;
|
||||
int8_t iStart, iEnd;
|
||||
size_t i;
|
||||
|
||||
MIN_NORM = 0.0f;
|
||||
|
||||
// Find max/min of input texels
|
||||
float fBlockMax = theTexelsU[0];
|
||||
float fBlockMin = theTexelsU[0];
|
||||
for (i = 0; i < BLOCK_SIZE; ++i)
|
||||
{
|
||||
fBlockMin = theTexelsU[i];
|
||||
}
|
||||
else if (theTexelsU[i]>fBlockMax)
|
||||
{
|
||||
fBlockMax = theTexelsU[i];
|
||||
}
|
||||
}
|
||||
|
||||
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
|
||||
// the exact code of the boundary values.
|
||||
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
|
||||
|
||||
// Using Optimize
|
||||
float fStart, fEnd;
|
||||
|
||||
if (!bUsing4BlockCodec)
|
||||
{
|
||||
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
|
||||
|
||||
iStart = (uint8_t) (fStart * 255.0f);
|
||||
iEnd = (uint8_t) (fEnd * 255.0f);
|
||||
|
||||
endpointU_0 = iEnd;
|
||||
endpointU_1 = iStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
|
||||
|
||||
iStart = (uint8_t) (fStart * 255.0f);
|
||||
iEnd = (uint8_t) (fEnd * 255.0f);
|
||||
|
||||
endpointU_1 = iEnd;
|
||||
endpointU_0 = iStart;
|
||||
}
|
||||
}
|
||||
|
||||
static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1)
|
||||
{
|
||||
// The boundary of codec for signed/unsigned format
|
||||
float MIN_NORM;
|
||||
float MAX_NORM = 1.0f;
|
||||
int8_t iStart, iEnd;
|
||||
size_t i;
|
||||
|
||||
MIN_NORM = -1.0f;
|
||||
|
||||
// Find max/min of input texels
|
||||
float fBlockMax = theTexelsU[0];
|
||||
float fBlockMin = theTexelsU[0];
|
||||
for (i = 0; i < BLOCK_SIZE; ++i)
|
||||
{
|
||||
if (theTexelsU[i]<fBlockMin)
|
||||
{
|
||||
fBlockMin = theTexelsU[i];
|
||||
}
|
||||
else if (theTexelsU[i]>fBlockMax)
|
||||
{
|
||||
fBlockMax = theTexelsU[i];
|
||||
}
|
||||
}
|
||||
|
||||
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
|
||||
// the exact code of the boundary values.
|
||||
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
|
||||
|
||||
// Using Optimize
|
||||
float fStart, fEnd;
|
||||
|
||||
if (!bUsing4BlockCodec)
|
||||
{
|
||||
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 8);
|
||||
|
||||
FloatToSNorm(fStart, &iStart);
|
||||
FloatToSNorm(fEnd, &iEnd);
|
||||
|
||||
endpointU_0 = iEnd;
|
||||
endpointU_1 = iStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 6);
|
||||
|
||||
FloatToSNorm(fStart, &iStart);
|
||||
FloatToSNorm(fEnd, &iEnd);
|
||||
|
||||
endpointU_1 = iEnd;
|
||||
endpointU_0 = iStart;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static inline void FindEndPointsBC5U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
|
||||
_Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1, _Out_ uint8_t &endpointV_0, _Out_ uint8_t &endpointV_1)
|
||||
{
|
||||
//Encoding the U and V channel by BC4 codec separately.
|
||||
FindEndPointsBC4U( theTexelsU, endpointU_0, endpointU_1);
|
||||
FindEndPointsBC4U( theTexelsV, endpointV_0, endpointV_1);
|
||||
}
|
||||
|
||||
static inline void FindEndPointsBC5S( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
|
||||
_Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1, _Out_ int8_t &endpointV_0, _Out_ int8_t &endpointV_1)
|
||||
{
|
||||
//Encoding the U and V channel by BC4 codec separately.
|
||||
FindEndPointsBC4S( theTexelsU, endpointU_0, endpointU_1);
|
||||
FindEndPointsBC4S( theTexelsV, endpointV_0, endpointV_1);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
|
||||
{
|
||||
float rGradient[8];
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
rGradient[i] = pBC->DecodeFromIndex(i);
|
||||
}
|
||||
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
size_t uBestIndex = 0;
|
||||
float fBestDelta = 100000;
|
||||
for (size_t uIndex = 0; uIndex < 8; uIndex++)
|
||||
{
|
||||
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
|
||||
if (fCurrentDelta < fBestDelta)
|
||||
if (theTexelsU[i] < fBlockMin)
|
||||
{
|
||||
uBestIndex = uIndex;
|
||||
fBestDelta = fCurrentDelta;
|
||||
fBlockMin = theTexelsU[i];
|
||||
}
|
||||
else if (theTexelsU[i] > fBlockMax)
|
||||
{
|
||||
fBlockMax = theTexelsU[i];
|
||||
}
|
||||
}
|
||||
pBC->SetIndex(i, uBestIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
|
||||
{
|
||||
float rGradient[8];
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
rGradient[i] = pBC->DecodeFromIndex(i);
|
||||
}
|
||||
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
size_t uBestIndex = 0;
|
||||
float fBestDelta = 100000;
|
||||
for (size_t uIndex = 0; uIndex < 8; uIndex++)
|
||||
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
|
||||
// the exact code of the boundary values.
|
||||
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
|
||||
|
||||
// Using Optimize
|
||||
float fStart, fEnd;
|
||||
|
||||
if (!bUsing4BlockCodec)
|
||||
{
|
||||
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
|
||||
if (fCurrentDelta < fBestDelta)
|
||||
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
|
||||
|
||||
iStart = (uint8_t)(fStart * 255.0f);
|
||||
iEnd = (uint8_t)(fEnd * 255.0f);
|
||||
|
||||
endpointU_0 = iEnd;
|
||||
endpointU_1 = iStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
|
||||
|
||||
iStart = (uint8_t)(fStart * 255.0f);
|
||||
iEnd = (uint8_t)(fEnd * 255.0f);
|
||||
|
||||
endpointU_1 = iEnd;
|
||||
endpointU_0 = iStart;
|
||||
}
|
||||
}
|
||||
|
||||
void FindEndPointsBC4S(
|
||||
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
|
||||
_Out_ int8_t &endpointU_0,
|
||||
_Out_ int8_t &endpointU_1)
|
||||
{
|
||||
// The boundary of codec for signed/unsigned format
|
||||
float MIN_NORM;
|
||||
float MAX_NORM = 1.0f;
|
||||
int8_t iStart, iEnd;
|
||||
size_t i;
|
||||
|
||||
MIN_NORM = -1.0f;
|
||||
|
||||
// Find max/min of input texels
|
||||
float fBlockMax = theTexelsU[0];
|
||||
float fBlockMin = theTexelsU[0];
|
||||
for (i = 0; i < BLOCK_SIZE; ++i)
|
||||
{
|
||||
if (theTexelsU[i] < fBlockMin)
|
||||
{
|
||||
uBestIndex = uIndex;
|
||||
fBestDelta = fCurrentDelta;
|
||||
fBlockMin = theTexelsU[i];
|
||||
}
|
||||
else if (theTexelsU[i] > fBlockMax)
|
||||
{
|
||||
fBlockMax = theTexelsU[i];
|
||||
}
|
||||
}
|
||||
pBC->SetIndex(i, uBestIndex);
|
||||
|
||||
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
|
||||
// the exact code of the boundary values.
|
||||
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
|
||||
|
||||
// Using Optimize
|
||||
float fStart, fEnd;
|
||||
|
||||
if (!bUsing4BlockCodec)
|
||||
{
|
||||
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 8);
|
||||
|
||||
FloatToSNorm(fStart, &iStart);
|
||||
FloatToSNorm(fEnd, &iEnd);
|
||||
|
||||
endpointU_0 = iEnd;
|
||||
endpointU_1 = iStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 6);
|
||||
|
||||
FloatToSNorm(fStart, &iStart);
|
||||
FloatToSNorm(fEnd, &iEnd);
|
||||
|
||||
endpointU_1 = iEnd;
|
||||
endpointU_0 = iStart;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline void FindEndPointsBC5U(
|
||||
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
|
||||
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
|
||||
_Out_ uint8_t &endpointU_0,
|
||||
_Out_ uint8_t &endpointU_1,
|
||||
_Out_ uint8_t &endpointV_0,
|
||||
_Out_ uint8_t &endpointV_1)
|
||||
{
|
||||
//Encoding the U and V channel by BC4 codec separately.
|
||||
FindEndPointsBC4U(theTexelsU, endpointU_0, endpointU_1);
|
||||
FindEndPointsBC4U(theTexelsV, endpointV_0, endpointV_1);
|
||||
}
|
||||
|
||||
inline void FindEndPointsBC5S(
|
||||
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
|
||||
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
|
||||
_Out_ int8_t &endpointU_0,
|
||||
_Out_ int8_t &endpointU_1,
|
||||
_Out_ int8_t &endpointV_0,
|
||||
_Out_ int8_t &endpointV_1)
|
||||
{
|
||||
//Encoding the U and V channel by BC4 codec separately.
|
||||
FindEndPointsBC4S(theTexelsU, endpointU_0, endpointU_1);
|
||||
FindEndPointsBC4S(theTexelsV, endpointV_0, endpointV_1);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void FindClosestUNORM(
|
||||
_Inout_ BC4_UNORM* pBC,
|
||||
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
|
||||
{
|
||||
float rGradient[8];
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
rGradient[i] = pBC->DecodeFromIndex(i);
|
||||
}
|
||||
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
size_t uBestIndex = 0;
|
||||
float fBestDelta = 100000;
|
||||
for (size_t uIndex = 0; uIndex < 8; uIndex++)
|
||||
{
|
||||
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
|
||||
if (fCurrentDelta < fBestDelta)
|
||||
{
|
||||
uBestIndex = uIndex;
|
||||
fBestDelta = fCurrentDelta;
|
||||
}
|
||||
}
|
||||
pBC->SetIndex(i, uBestIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void FindClosestSNORM(
|
||||
_Inout_ BC4_SNORM* pBC,
|
||||
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
|
||||
{
|
||||
float rGradient[8];
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
rGradient[i] = pBC->DecodeFromIndex(i);
|
||||
}
|
||||
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
size_t uBestIndex = 0;
|
||||
float fBestDelta = 100000;
|
||||
for (size_t uIndex = 0; uIndex < 8; uIndex++)
|
||||
{
|
||||
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
|
||||
if (fCurrentDelta < fBestDelta)
|
||||
{
|
||||
uBestIndex = uIndex;
|
||||
fBestDelta = fCurrentDelta;
|
||||
}
|
||||
}
|
||||
pBC->SetIndex(i, uBestIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,42 +392,42 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
|
||||
// BC4 Compression
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
void D3DXDecodeBC4U( XMVECTOR *pColor, const uint8_t *pBC )
|
||||
void DirectX::D3DXDecodeBC4U(XMVECTOR *pColor, const uint8_t *pBC)
|
||||
{
|
||||
assert( pColor && pBC );
|
||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
||||
assert(pColor && pBC);
|
||||
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
|
||||
|
||||
auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
void D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
|
||||
void DirectX::D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
|
||||
{
|
||||
assert( pColor && pBC );
|
||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
||||
assert(pColor && pBC);
|
||||
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
|
||||
|
||||
auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
void DirectX::D3DXEncodeBC4U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
||||
{
|
||||
UNREFERENCED_PARAMETER( flags );
|
||||
UNREFERENCED_PARAMETER(flags);
|
||||
|
||||
assert( pBC && pColor );
|
||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
||||
assert(pBC && pColor);
|
||||
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
|
||||
|
||||
memset(pBC, 0, sizeof(BC4_UNORM));
|
||||
auto pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
|
||||
@ -413,7 +435,7 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
theTexelsU[i] = XMVectorGetX( pColor[i] );
|
||||
theTexelsU[i] = XMVectorGetX(pColor[i]);
|
||||
}
|
||||
|
||||
FindEndPointsBC4U(theTexelsU, pBC4->red_0, pBC4->red_1);
|
||||
@ -421,12 +443,12 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
void DirectX::D3DXEncodeBC4S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
||||
{
|
||||
UNREFERENCED_PARAMETER( flags );
|
||||
UNREFERENCED_PARAMETER(flags);
|
||||
|
||||
assert( pBC && pColor );
|
||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
||||
assert(pBC && pColor);
|
||||
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
|
||||
|
||||
memset(pBC, 0, sizeof(BC4_UNORM));
|
||||
auto pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
|
||||
@ -434,7 +456,7 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
theTexelsU[i] = XMVectorGetX( pColor[i] );
|
||||
theTexelsU[i] = XMVectorGetX(pColor[i]);
|
||||
}
|
||||
|
||||
FindEndPointsBC4S(theTexelsU, pBC4->red_0, pBC4->red_1);
|
||||
@ -446,55 +468,55 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
// BC5 Compression
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
void D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
|
||||
void DirectX::D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
|
||||
{
|
||||
assert( pColor && pBC );
|
||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
||||
assert(pColor && pBC);
|
||||
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
|
||||
|
||||
auto pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
|
||||
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
|
||||
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
void D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
|
||||
void DirectX::D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
|
||||
{
|
||||
assert( pColor && pBC );
|
||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
||||
assert(pColor && pBC);
|
||||
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
|
||||
|
||||
auto pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
|
||||
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
|
||||
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
|
||||
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
void DirectX::D3DXEncodeBC5U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
||||
{
|
||||
UNREFERENCED_PARAMETER( flags );
|
||||
UNREFERENCED_PARAMETER(flags);
|
||||
|
||||
assert( pBC && pColor );
|
||||
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
|
||||
assert(pBC && pColor);
|
||||
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
|
||||
|
||||
memset(pBC, 0, sizeof(BC4_UNORM)*2);
|
||||
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
|
||||
auto pBCR = reinterpret_cast<BC4_UNORM*>(pBC);
|
||||
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
|
||||
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
|
||||
float theTexelsU[NUM_PIXELS_PER_BLOCK];
|
||||
float theTexelsV[NUM_PIXELS_PER_BLOCK];
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
XMFLOAT4A clr;
|
||||
XMStoreFloat4A( &clr, pColor[i] );
|
||||
XMStoreFloat4A(&clr, pColor[i]);
|
||||
theTexelsU[i] = clr.x;
|
||||
theTexelsV[i] = clr.y;
|
||||
}
|
||||
@ -512,23 +534,23 @@ void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
void DirectX::D3DXEncodeBC5S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
|
||||
{
|
||||
UNREFERENCED_PARAMETER( flags );
|
||||
UNREFERENCED_PARAMETER(flags);
|
||||
|
||||
assert( pBC && pColor );
|
||||
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
|
||||
assert(pBC && pColor);
|
||||
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
|
||||
|
||||
memset(pBC, 0, sizeof(BC4_UNORM)*2);
|
||||
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
|
||||
auto pBCR = reinterpret_cast<BC4_SNORM*>(pBC);
|
||||
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
|
||||
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
|
||||
float theTexelsU[NUM_PIXELS_PER_BLOCK];
|
||||
float theTexelsV[NUM_PIXELS_PER_BLOCK];
|
||||
|
||||
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
|
||||
{
|
||||
XMFLOAT4A clr;
|
||||
XMStoreFloat4A( &clr, pColor[i] );
|
||||
XMStoreFloat4A(&clr, pColor[i]);
|
||||
theTexelsU[i] = clr.x;
|
||||
theTexelsV[i] = clr.y;
|
||||
}
|
||||
@ -544,5 +566,3 @@ void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
|
||||
FindClosestSNORM(pBCR, theTexelsU);
|
||||
FindClosestSNORM(pBCG, theTexelsV);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@
|
||||
#pragma comment(lib,"dxguid.lib")
|
||||
#endif
|
||||
|
||||
using namespace DirectX;
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace
|
||||
@ -82,9 +83,6 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
namespace DirectX
|
||||
{
|
||||
|
||||
GPUCompressBC::GPUCompressBC() :
|
||||
m_bcformat(DXGI_FORMAT_UNKNOWN),
|
||||
m_srcformat(DXGI_FORMAT_UNKNOWN),
|
||||
@ -97,79 +95,79 @@ GPUCompressBC::GPUCompressBC() :
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
|
||||
HRESULT GPUCompressBC::Initialize(ID3D11Device* pDevice)
|
||||
{
|
||||
if ( !pDevice )
|
||||
if (!pDevice)
|
||||
return E_INVALIDARG;
|
||||
|
||||
// Check for DirectCompute support
|
||||
D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel();
|
||||
|
||||
if ( fl < D3D_FEATURE_LEVEL_10_0 )
|
||||
if (fl < D3D_FEATURE_LEVEL_10_0)
|
||||
{
|
||||
// DirectCompute not supported on Feature Level 9.x hardware
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if ( fl < D3D_FEATURE_LEVEL_11_0 )
|
||||
if (fl < D3D_FEATURE_LEVEL_11_0)
|
||||
{
|
||||
// DirectCompute support on Feature Level 10.x hardware is optional, and this function needs it
|
||||
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts;
|
||||
HRESULT hr = pDevice->CheckFeatureSupport( D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
memset( &hwopts, 0, sizeof(hwopts) );
|
||||
memset(&hwopts, 0, sizeof(hwopts));
|
||||
}
|
||||
|
||||
if ( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x )
|
||||
if (!hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x)
|
||||
{
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
// Save a device reference and obtain immediate context
|
||||
m_device = pDevice;
|
||||
|
||||
pDevice->GetImmediateContext( m_context.ReleaseAndGetAddressOf() );
|
||||
assert( m_context );
|
||||
pDevice->GetImmediateContext(m_context.ReleaseAndGetAddressOf());
|
||||
assert(m_context);
|
||||
|
||||
//--- Create compute shader library: BC6H -----------------------------------------
|
||||
|
||||
// Modes 11-14
|
||||
HRESULT hr = pDevice->CreateComputeShader( BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateComputeShader(BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Modes 1-10
|
||||
hr = pDevice->CreateComputeShader( BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateComputeShader(BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Encode
|
||||
hr = pDevice->CreateComputeShader( BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateComputeShader(BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
//--- Create compute shader library: BC7 ------------------------------------------
|
||||
|
||||
// Modes 4, 5, 6
|
||||
hr = pDevice->CreateComputeShader( BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateComputeShader(BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Modes 1, 3, 7
|
||||
hr = pDevice->CreateComputeShader( BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateComputeShader(BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Modes 0, 2
|
||||
hr = pDevice->CreateComputeShader( BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateComputeShader(BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Encode
|
||||
hr = pDevice->CreateComputeShader( BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateComputeShader(BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return S_OK;
|
||||
@ -178,12 +176,12 @@ HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format, float alphaWeight, bool skip3subsets )
|
||||
HRESULT GPUCompressBC::Prepare(size_t width, size_t height, DXGI_FORMAT format, float alphaWeight, bool skip3subsets)
|
||||
{
|
||||
if ( !width || !height || alphaWeight < 0.f )
|
||||
if (!width || !height || alphaWeight < 0.f)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( (width > UINT32_MAX) || (height > UINT32_MAX) )
|
||||
if ((width > UINT32_MAX) || (height > UINT32_MAX))
|
||||
return E_INVALIDARG;
|
||||
|
||||
m_width = width;
|
||||
@ -193,20 +191,20 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
||||
|
||||
m_skip3Subsets = skip3subsets;
|
||||
|
||||
size_t xblocks = std::max<size_t>( 1, (width + 3) >> 2 );
|
||||
size_t yblocks = std::max<size_t>( 1, (height + 3) >> 2 );
|
||||
size_t xblocks = std::max<size_t>(1, (width + 3) >> 2);
|
||||
size_t yblocks = std::max<size_t>(1, (height + 3) >> 2);
|
||||
size_t num_blocks = xblocks * yblocks;
|
||||
|
||||
switch( format )
|
||||
switch (format)
|
||||
{
|
||||
// BC6H GPU compressor takes RGBAF32 as input
|
||||
// BC6H GPU compressor takes RGBAF32 as input
|
||||
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||
case DXGI_FORMAT_BC6H_UF16:
|
||||
case DXGI_FORMAT_BC6H_SF16:
|
||||
m_srcformat = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
break;
|
||||
|
||||
// BC7 GPU compressor takes RGBA32 as input
|
||||
// BC7 GPU compressor takes RGBA32 as input
|
||||
case DXGI_FORMAT_BC7_TYPELESS:
|
||||
case DXGI_FORMAT_BC7_UNORM:
|
||||
m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
@ -218,39 +216,39 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
||||
|
||||
default:
|
||||
m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN;
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
m_bcformat = format;
|
||||
|
||||
auto pDevice = m_device.Get();
|
||||
if ( !pDevice )
|
||||
if (!pDevice)
|
||||
return E_POINTER;
|
||||
|
||||
// Create structured buffers
|
||||
size_t bufferSize = num_blocks * sizeof( BufferBC6HBC7 );
|
||||
size_t bufferSize = num_blocks * sizeof(BufferBC6HBC7);
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
|
||||
desc.StructureByteStride = sizeof( BufferBC6HBC7 );
|
||||
desc.ByteWidth = static_cast<UINT>( bufferSize );
|
||||
desc.StructureByteStride = sizeof(BufferBC6HBC7);
|
||||
desc.ByteWidth = static_cast<UINT>(bufferSize);
|
||||
|
||||
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_output.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_output.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pDevice->CreateBuffer( &desc, nullptr, m_err1.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateBuffer(&desc, nullptr, m_err1.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pDevice->CreateBuffer( &desc, nullptr, m_err2.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateBuffer(&desc, nullptr, m_err2.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
@ -261,10 +259,10 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.ByteWidth = static_cast<UINT>( bufferSize );
|
||||
desc.ByteWidth = static_cast<UINT>(bufferSize);
|
||||
|
||||
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
@ -276,10 +274,10 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.ByteWidth = sizeof( ConstantsBC6HBC7 );
|
||||
desc.ByteWidth = sizeof(ConstantsBC6HBC7);
|
||||
|
||||
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
@ -288,17 +286,17 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
||||
// Create shader resource views
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
|
||||
desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
|
||||
desc.Buffer.NumElements = static_cast<UINT>(num_blocks);
|
||||
desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||
|
||||
HRESULT hr = pDevice->CreateShaderResourceView( m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateShaderResourceView(m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pDevice->CreateShaderResourceView( m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateShaderResourceView(m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
@ -307,23 +305,23 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
||||
// Create unordered access views
|
||||
{
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
|
||||
desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
|
||||
desc.Buffer.NumElements = static_cast<UINT>(num_blocks);
|
||||
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
||||
|
||||
HRESULT hr = pDevice->CreateUnorderedAccessView( m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateUnorderedAccessView(m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pDevice->CreateUnorderedAccessView( m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateUnorderedAccessView(m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = pDevice->CreateUnorderedAccessView( m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
hr = pDevice->CreateUnorderedAccessView(m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
@ -335,34 +333,34 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
||||
HRESULT GPUCompressBC::Compress(const Image& srcImage, const Image& destImage)
|
||||
{
|
||||
if ( !srcImage.pixels || !destImage.pixels )
|
||||
if (!srcImage.pixels || !destImage.pixels)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( srcImage.width != destImage.width
|
||||
|| srcImage.height != destImage.height
|
||||
|| srcImage.width != m_width
|
||||
|| srcImage.height != m_height
|
||||
|| srcImage.format != m_srcformat
|
||||
|| destImage.format != m_bcformat )
|
||||
if (srcImage.width != destImage.width
|
||||
|| srcImage.height != destImage.height
|
||||
|| srcImage.width != m_width
|
||||
|| srcImage.height != m_height
|
||||
|| srcImage.format != m_srcformat
|
||||
|| destImage.format != m_bcformat)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
//--- Create input texture --------------------------------------------------------
|
||||
auto pDevice = m_device.Get();
|
||||
if ( !pDevice )
|
||||
if (!pDevice)
|
||||
return E_POINTER;
|
||||
|
||||
// We need to avoid the hardware doing additional colorspace conversion
|
||||
DXGI_FORMAT inputFormat = ( m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
|
||||
DXGI_FORMAT inputFormat = (m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
|
||||
|
||||
ComPtr<ID3D11Texture2D> sourceTex;
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
desc.Width = static_cast<UINT>( srcImage.width );
|
||||
desc.Height = static_cast<UINT>( srcImage.height );
|
||||
desc.Width = static_cast<UINT>(srcImage.width);
|
||||
desc.Height = static_cast<UINT>(srcImage.height);
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = inputFormat;
|
||||
@ -372,11 +370,11 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
initData.pSysMem = srcImage.pixels;
|
||||
initData.SysMemPitch = static_cast<DWORD>( srcImage.rowPitch );
|
||||
initData.SysMemSlicePitch = static_cast<DWORD>( srcImage.slicePitch );
|
||||
initData.SysMemPitch = static_cast<DWORD>(srcImage.rowPitch);
|
||||
initData.SysMemSlicePitch = static_cast<DWORD>(srcImage.slicePitch);
|
||||
|
||||
HRESULT hr = pDevice->CreateTexture2D( &desc, &initData, sourceTex.GetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateTexture2D(&desc, &initData, sourceTex.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
@ -389,8 +387,8 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
||||
desc.Format = inputFormat;
|
||||
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
|
||||
HRESULT hr = pDevice->CreateShaderResourceView( sourceTex.Get(), &desc, sourceSRV.GetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pDevice->CreateShaderResourceView(sourceTex.Get(), &desc, sourceSRV.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
@ -398,7 +396,7 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
||||
|
||||
//--- Compress using DirectCompute ------------------------------------------------
|
||||
bool isbc7 = false;
|
||||
switch( m_bcformat )
|
||||
switch (m_bcformat)
|
||||
{
|
||||
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||
case DXGI_FORMAT_BC6H_UF16:
|
||||
@ -418,47 +416,47 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
||||
const UINT MAX_BLOCK_BATCH = 64;
|
||||
|
||||
auto pContext = m_context.Get();
|
||||
if ( !pContext )
|
||||
if (!pContext)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
size_t xblocks = std::max<size_t>( 1, (m_width + 3) >> 2 );
|
||||
size_t yblocks = std::max<size_t>( 1, (m_height + 3) >> 2 );
|
||||
size_t xblocks = std::max<size_t>(1, (m_width + 3) >> 2);
|
||||
size_t yblocks = std::max<size_t>(1, (m_height + 3) >> 2);
|
||||
|
||||
UINT num_total_blocks = static_cast<UINT>( xblocks * yblocks );
|
||||
UINT num_total_blocks = static_cast<UINT>(xblocks * yblocks);
|
||||
UINT num_blocks = num_total_blocks;
|
||||
int start_block_id = 0;
|
||||
while (num_blocks > 0)
|
||||
{
|
||||
UINT n = std::min<UINT>( num_blocks, MAX_BLOCK_BATCH );
|
||||
UINT n = std::min<UINT>(num_blocks, MAX_BLOCK_BATCH);
|
||||
UINT uThreadGroupCount = n;
|
||||
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ConstantsBC6HBC7 param;
|
||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
||||
param.num_block_x = static_cast<UINT>( xblocks );
|
||||
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||
param.num_block_x = static_cast<UINT>(xblocks);
|
||||
param.format = m_bcformat;
|
||||
param.mode_id = 0;
|
||||
param.start_block_id = start_block_id;
|
||||
param.num_total_blocks = num_total_blocks;
|
||||
param.alpha_weight = m_alphaWeight;
|
||||
memcpy( mapped.pData, ¶m, sizeof( param ) );
|
||||
memcpy(mapped.pData, ¶m, sizeof(param));
|
||||
|
||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
||||
pContext->Unmap(m_constBuffer.Get(), 0);
|
||||
}
|
||||
|
||||
if ( isbc7 )
|
||||
if (isbc7)
|
||||
{
|
||||
//--- BC7 -----------------------------------------------------------------
|
||||
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
|
||||
RunComputeShader( pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
|
||||
RunComputeShader(pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_err1UAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
|
||||
|
||||
for ( UINT i = 0; i < 3; ++i )
|
||||
for (UINT i = 0; i < 3; ++i)
|
||||
{
|
||||
static const UINT modes[] = { 1, 3, 7 };
|
||||
|
||||
@ -467,141 +465,139 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
|
||||
// Mode 7: err1 -> err2
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ResetContext( pContext );
|
||||
ResetContext(pContext);
|
||||
return hr;
|
||||
}
|
||||
|
||||
ConstantsBC6HBC7 param;
|
||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
||||
param.num_block_x = static_cast<UINT>( xblocks );
|
||||
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||
param.num_block_x = static_cast<UINT>(xblocks);
|
||||
param.format = m_bcformat;
|
||||
param.mode_id = modes[i];
|
||||
param.start_block_id = start_block_id;
|
||||
param.num_total_blocks = num_total_blocks;
|
||||
param.alpha_weight = m_alphaWeight;
|
||||
memcpy( mapped.pData, ¶m, sizeof( param ) );
|
||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
||||
memcpy(mapped.pData, ¶m, sizeof(param));
|
||||
pContext->Unmap(m_constBuffer.Get(), 0);
|
||||
}
|
||||
|
||||
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
|
||||
RunComputeShader( pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount );
|
||||
RunComputeShader(pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount);
|
||||
}
|
||||
|
||||
if ( !m_skip3Subsets )
|
||||
if (!m_skip3Subsets)
|
||||
{
|
||||
// 3 subset modes tend to be used rarely and add significant compression time
|
||||
for ( UINT i = 0; i < 2; ++i )
|
||||
for (UINT i = 0; i < 2; ++i)
|
||||
{
|
||||
static const UINT modes[] = { 0, 2 };
|
||||
// Mode 0: err2 -> err1
|
||||
// Mode 2: err1 -> err2
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ResetContext( pContext );
|
||||
ResetContext(pContext);
|
||||
return hr;
|
||||
}
|
||||
|
||||
ConstantsBC6HBC7 param;
|
||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
||||
param.num_block_x = static_cast<UINT>( xblocks );
|
||||
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||
param.num_block_x = static_cast<UINT>(xblocks);
|
||||
param.format = m_bcformat;
|
||||
param.mode_id = modes[i];
|
||||
param.start_block_id = start_block_id;
|
||||
param.num_total_blocks = num_total_blocks;
|
||||
param.alpha_weight = m_alphaWeight;
|
||||
memcpy( mapped.pData, ¶m, sizeof( param ) );
|
||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
||||
memcpy(mapped.pData, ¶m, sizeof(param));
|
||||
pContext->Unmap(m_constBuffer.Get(), 0);
|
||||
}
|
||||
|
||||
pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get();
|
||||
RunComputeShader( pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount );
|
||||
RunComputeShader(pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount);
|
||||
}
|
||||
}
|
||||
|
||||
pSRVs[1] = m_err2SRV.Get();
|
||||
RunComputeShader( pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
|
||||
RunComputeShader(pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- BC6H ----------------------------------------------------------------
|
||||
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
|
||||
RunComputeShader( pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
|
||||
RunComputeShader(pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_err1UAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
|
||||
|
||||
for ( UINT i = 0; i < 10; ++i )
|
||||
for (UINT i = 0; i < 10; ++i)
|
||||
{
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ResetContext( pContext );
|
||||
ResetContext(pContext);
|
||||
return hr;
|
||||
}
|
||||
|
||||
ConstantsBC6HBC7 param;
|
||||
param.tex_width = static_cast<UINT>( srcImage.width );
|
||||
param.num_block_x = static_cast<UINT>( xblocks );
|
||||
param.tex_width = static_cast<UINT>(srcImage.width);
|
||||
param.num_block_x = static_cast<UINT>(xblocks);
|
||||
param.format = m_bcformat;
|
||||
param.mode_id = i;
|
||||
param.start_block_id = start_block_id;
|
||||
param.num_total_blocks = num_total_blocks;
|
||||
memcpy( mapped.pData, ¶m, sizeof( param ) );
|
||||
pContext->Unmap( m_constBuffer.Get(), 0 );
|
||||
memcpy(mapped.pData, ¶m, sizeof(param));
|
||||
pContext->Unmap(m_constBuffer.Get(), 0);
|
||||
}
|
||||
|
||||
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
|
||||
RunComputeShader( pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
|
||||
RunComputeShader(pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
|
||||
}
|
||||
|
||||
pSRVs[1] = m_err1SRV.Get();
|
||||
RunComputeShader( pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
|
||||
RunComputeShader(pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
|
||||
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
|
||||
}
|
||||
|
||||
start_block_id += n;
|
||||
num_blocks -= n;
|
||||
}
|
||||
|
||||
ResetContext( pContext );
|
||||
ResetContext(pContext);
|
||||
|
||||
//--- Copy output texture back to CPU ---------------------------------------------
|
||||
|
||||
pContext->CopyResource( m_outputCPU.Get(), m_output.Get() );
|
||||
pContext->CopyResource(m_outputCPU.Get(), m_output.Get());
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
HRESULT hr = pContext->Map( m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped );
|
||||
if ( SUCCEEDED(hr) )
|
||||
HRESULT hr = pContext->Map(m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
const uint8_t *pSrc = reinterpret_cast<const uint8_t *>( mapped.pData );
|
||||
const uint8_t *pSrc = reinterpret_cast<const uint8_t *>(mapped.pData);
|
||||
uint8_t *pDest = destImage.pixels;
|
||||
|
||||
size_t pitch = xblocks * sizeof( BufferBC6HBC7 );
|
||||
size_t pitch = xblocks * sizeof(BufferBC6HBC7);
|
||||
|
||||
size_t rows = std::max<size_t>( 1, ( destImage.height + 3 ) >> 2 );
|
||||
size_t rows = std::max<size_t>(1, (destImage.height + 3) >> 2);
|
||||
|
||||
for( size_t h = 0; h < rows; ++h )
|
||||
for (size_t h = 0; h < rows; ++h)
|
||||
{
|
||||
memcpy( pDest, pSrc, destImage.rowPitch );
|
||||
memcpy(pDest, pSrc, destImage.rowPitch);
|
||||
|
||||
pSrc += pitch;
|
||||
pDest += destImage.rowPitch;
|
||||
}
|
||||
|
||||
pContext->Unmap( m_outputCPU.Get(), 0 );
|
||||
pContext->Unmap(m_outputCPU.Get(), 0);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
}; // namespace
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include <ocidl.h>
|
||||
|
||||
#define DIRECTX_TEX_VERSION 134
|
||||
#define DIRECTX_TEX_VERSION 140
|
||||
|
||||
struct IWICImagingFactory;
|
||||
struct IWICMetadataQueryReader;
|
||||
@ -204,21 +204,21 @@ namespace DirectX
|
||||
// Filtering mode to use for any required image resizing (only needed when loading arrays of differently sized images; defaults to Fant)
|
||||
};
|
||||
|
||||
HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
_Out_ TexMetadata& metadata );
|
||||
HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
|
||||
HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
|
||||
_Out_ TexMetadata& metadata );
|
||||
|
||||
HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
|
||||
HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
||||
_Out_ TexMetadata& metadata );
|
||||
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
|
||||
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ const wchar_t* szFile,
|
||||
_Out_ TexMetadata& metadata );
|
||||
|
||||
HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
_Out_ TexMetadata& metadata,
|
||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
||||
|
||||
HRESULT __cdecl GetMetadataFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
|
||||
HRESULT __cdecl GetMetadataFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
|
||||
_Out_ TexMetadata& metadata,
|
||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
||||
|
||||
@ -238,13 +238,16 @@ namespace DirectX
|
||||
{
|
||||
public:
|
||||
ScratchImage()
|
||||
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) {}
|
||||
: m_nimages(0), m_size(0), m_image(nullptr), m_memory(nullptr) {}
|
||||
ScratchImage(ScratchImage&& moveFrom)
|
||||
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) { *this = std::move(moveFrom); }
|
||||
: m_nimages(0), m_size(0), m_image(nullptr), m_memory(nullptr) { *this = std::move(moveFrom); }
|
||||
~ScratchImage() { Release(); }
|
||||
|
||||
ScratchImage& __cdecl operator= (ScratchImage&& moveFrom);
|
||||
|
||||
ScratchImage(const ScratchImage&) = delete;
|
||||
ScratchImage& operator=(const ScratchImage&) = delete;
|
||||
|
||||
HRESULT __cdecl Initialize( _In_ const TexMetadata& mdata, _In_ DWORD flags = CP_FLAGS_NONE );
|
||||
|
||||
HRESULT __cdecl Initialize1D( _In_ DXGI_FORMAT fmt, _In_ size_t length, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
|
||||
@ -261,27 +264,23 @@ namespace DirectX
|
||||
|
||||
bool __cdecl OverrideFormat( _In_ DXGI_FORMAT f );
|
||||
|
||||
const TexMetadata& __cdecl GetMetadata() const { return _metadata; }
|
||||
const TexMetadata& __cdecl GetMetadata() const { return m_metadata; }
|
||||
const Image* __cdecl GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const;
|
||||
|
||||
const Image* __cdecl GetImages() const { return _image; }
|
||||
size_t __cdecl GetImageCount() const { return _nimages; }
|
||||
const Image* __cdecl GetImages() const { return m_image; }
|
||||
size_t __cdecl GetImageCount() const { return m_nimages; }
|
||||
|
||||
uint8_t* __cdecl GetPixels() const { return _memory; }
|
||||
size_t __cdecl GetPixelsSize() const { return _size; }
|
||||
uint8_t* __cdecl GetPixels() const { return m_memory; }
|
||||
size_t __cdecl GetPixelsSize() const { return m_size; }
|
||||
|
||||
bool __cdecl IsAlphaAllOpaque() const;
|
||||
|
||||
private:
|
||||
size_t _nimages;
|
||||
size_t _size;
|
||||
TexMetadata _metadata;
|
||||
Image* _image;
|
||||
uint8_t* _memory;
|
||||
|
||||
// Hide copy constructor and assignment operator
|
||||
ScratchImage( const ScratchImage& );
|
||||
ScratchImage& operator=( const ScratchImage& );
|
||||
size_t m_nimages;
|
||||
size_t m_size;
|
||||
TexMetadata m_metadata;
|
||||
Image* m_image;
|
||||
uint8_t* m_memory;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
@ -289,35 +288,34 @@ namespace DirectX
|
||||
class Blob
|
||||
{
|
||||
public:
|
||||
Blob() : _buffer(nullptr), _size(0) {}
|
||||
Blob(Blob&& moveFrom) : _buffer(nullptr), _size(0) { *this = std::move(moveFrom); }
|
||||
Blob() : m_buffer(nullptr), m_size(0) {}
|
||||
Blob(Blob&& moveFrom) : m_buffer(nullptr), m_size(0) { *this = std::move(moveFrom); }
|
||||
~Blob() { Release(); }
|
||||
|
||||
Blob& __cdecl operator= (Blob&& moveFrom);
|
||||
|
||||
Blob(const Blob&) = delete;
|
||||
Blob& operator=(const Blob&) = delete;
|
||||
|
||||
HRESULT __cdecl Initialize( _In_ size_t size );
|
||||
|
||||
void __cdecl Release();
|
||||
|
||||
void *__cdecl GetBufferPointer() const { return _buffer; }
|
||||
size_t __cdecl GetBufferSize() const { return _size; }
|
||||
void *__cdecl GetBufferPointer() const { return m_buffer; }
|
||||
size_t __cdecl GetBufferSize() const { return m_size; }
|
||||
|
||||
private:
|
||||
void* _buffer;
|
||||
size_t _size;
|
||||
|
||||
// Hide copy constructor and assignment operator
|
||||
Blob( const Blob& );
|
||||
Blob& operator=( const Blob& );
|
||||
void* m_buffer;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Image I/O
|
||||
|
||||
// DDS operations
|
||||
HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
|
||||
HRESULT __cdecl LoadFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
|
||||
HRESULT __cdecl LoadFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
|
||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
|
||||
|
||||
HRESULT __cdecl SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags,
|
||||
@ -325,23 +323,23 @@ namespace DirectX
|
||||
HRESULT __cdecl SaveToDDSMemory( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags,
|
||||
_Out_ Blob& blob );
|
||||
|
||||
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
|
||||
HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
|
||||
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ const wchar_t* szFile );
|
||||
HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ const wchar_t* szFile );
|
||||
|
||||
// TGA operations
|
||||
HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
|
||||
HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size,
|
||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
|
||||
HRESULT __cdecl LoadFromTGAFile( _In_z_ LPCWSTR szFile,
|
||||
HRESULT __cdecl LoadFromTGAFile( _In_z_ const wchar_t* szFile,
|
||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
|
||||
|
||||
HRESULT __cdecl SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );
|
||||
HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ LPCWSTR szFile );
|
||||
HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ const wchar_t* szFile );
|
||||
|
||||
// WIC operations
|
||||
HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
|
||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
|
||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
||||
HRESULT __cdecl LoadFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
|
||||
HRESULT __cdecl LoadFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
|
||||
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
|
||||
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
|
||||
|
||||
@ -353,10 +351,10 @@ namespace DirectX
|
||||
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
|
||||
|
||||
HRESULT __cdecl SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
|
||||
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
|
||||
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
|
||||
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
|
||||
HRESULT __cdecl SaveToWICFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
|
||||
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
|
||||
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
|
||||
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
|
@ -113,7 +113,7 @@ inline HRESULT __cdecl SaveToDDSMemory(const Image& image, DWORD flags, Blob& bl
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, LPCWSTR szFile)
|
||||
inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, const wchar_t* szFile)
|
||||
{
|
||||
TexMetadata mdata = {};
|
||||
mdata.width = image.width;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,178 +17,190 @@
|
||||
|
||||
#include "bcdirectcompute.h"
|
||||
|
||||
namespace DirectX
|
||||
using namespace DirectX;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
|
||||
{
|
||||
static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
|
||||
static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
|
||||
static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
|
||||
return ( compress & TEX_COMPRESS_SRGB );
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed
|
||||
//-------------------------------------------------------------------------------------
|
||||
static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& image, bool srgb, _In_ DWORD filter )
|
||||
{
|
||||
if ( !srcImage.pixels )
|
||||
return E_POINTER;
|
||||
|
||||
DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
const Image *img = image.GetImage( 0, 0, 0 );
|
||||
if ( !img )
|
||||
inline DWORD GetSRGBFlags(_In_ DWORD compress)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
static_assert(TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
|
||||
static_assert(TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
|
||||
static_assert(TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
|
||||
return (compress & TEX_COMPRESS_SRGB);
|
||||
}
|
||||
|
||||
uint8_t* pDest = img->pixels;
|
||||
if ( !pDest )
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed
|
||||
//-------------------------------------------------------------------------------------
|
||||
HRESULT ConvertToRGBA32(
|
||||
const Image& srcImage,
|
||||
ScratchImage& image,
|
||||
bool srgb,
|
||||
DWORD filter)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( ( sizeof(XMVECTOR) * srcImage.width ), 16 ) ) );
|
||||
if ( !scanline )
|
||||
{
|
||||
image.Release();
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
for( size_t h = 0; h < srcImage.height; ++h )
|
||||
{
|
||||
if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
|
||||
{
|
||||
image.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
_ConvertScanline( scanline.get(), srcImage.width, format, srcImage.format, filter );
|
||||
|
||||
if ( !_StoreScanline( pDest, img->rowPitch, format, scanline.get(), srcImage.width ) )
|
||||
{
|
||||
image.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += img->rowPitch;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
|
||||
//-------------------------------------------------------------------------------------
|
||||
static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image, _In_ DWORD filter )
|
||||
{
|
||||
if ( !srcImage.pixels )
|
||||
return E_POINTER;
|
||||
|
||||
HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
const Image *img = image.GetImage( 0, 0, 0 );
|
||||
if ( !img )
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
uint8_t* pDest = img->pixels;
|
||||
if ( !pDest )
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
for( size_t h = 0; h < srcImage.height; ++h )
|
||||
{
|
||||
if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
|
||||
{
|
||||
image.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
_ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += img->rowPitch;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Compress using GPU, converting to the proper input format for the shader if needed
|
||||
//-------------------------------------------------------------------------------------
|
||||
inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& srcImage, _In_ const Image& destImage, _In_ DWORD compress )
|
||||
{
|
||||
if ( !gpubc )
|
||||
return E_POINTER;
|
||||
|
||||
assert( srcImage.pixels && destImage.pixels );
|
||||
|
||||
DXGI_FORMAT format = gpubc->GetSourceFormat();
|
||||
|
||||
if ( srcImage.format == format )
|
||||
{
|
||||
// Input is already in our required source format
|
||||
return gpubc->Compress( srcImage, destImage );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert format and then use as the source image
|
||||
ScratchImage image;
|
||||
HRESULT hr;
|
||||
|
||||
DWORD srgb = _GetSRGBFlags( compress );
|
||||
|
||||
switch( format )
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
hr = _ConvertToRGBA32( srcImage, image, false, srgb );
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
hr = _ConvertToRGBA32( srcImage, image, true, srgb );
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
hr = _ConvertToRGBAF32( srcImage, image, srgb );
|
||||
break;
|
||||
|
||||
default:
|
||||
hr = E_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
const Image *img = image.GetImage( 0, 0, 0 );
|
||||
if ( !img )
|
||||
if (!srcImage.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
return gpubc->Compress( *img, destImage );
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *img = image.GetImage(0, 0, 0);
|
||||
if (!img)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
uint8_t* pDest = img->pixels;
|
||||
if (!pDest)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR) * srcImage.width), 16)));
|
||||
if (!scanline)
|
||||
{
|
||||
image.Release();
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
for (size_t h = 0; h < srcImage.height; ++h)
|
||||
{
|
||||
if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||
{
|
||||
image.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
_ConvertScanline(scanline.get(), srcImage.width, format, srcImage.format, filter);
|
||||
|
||||
if (!_StoreScanline(pDest, img->rowPitch, format, scanline.get(), srcImage.width))
|
||||
{
|
||||
image.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += img->rowPitch;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
|
||||
//-------------------------------------------------------------------------------------
|
||||
HRESULT ConvertToRGBAF32(
|
||||
const Image& srcImage,
|
||||
ScratchImage& image,
|
||||
DWORD filter)
|
||||
{
|
||||
if (!srcImage.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
HRESULT hr = image.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *img = image.GetImage(0, 0, 0);
|
||||
if (!img)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
uint8_t* pDest = img->pixels;
|
||||
if (!pDest)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
for (size_t h = 0; h < srcImage.height; ++h)
|
||||
{
|
||||
if (!_LoadScanline(reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||
{
|
||||
image.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
_ConvertScanline(reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter);
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += img->rowPitch;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Compress using GPU, converting to the proper input format for the shader if needed
|
||||
//-------------------------------------------------------------------------------------
|
||||
inline HRESULT GPUCompress(
|
||||
_In_ GPUCompressBC* gpubc,
|
||||
const Image& srcImage,
|
||||
const Image& destImage,
|
||||
DWORD compress)
|
||||
{
|
||||
if (!gpubc)
|
||||
return E_POINTER;
|
||||
|
||||
assert(srcImage.pixels && destImage.pixels);
|
||||
|
||||
DXGI_FORMAT format = gpubc->GetSourceFormat();
|
||||
|
||||
if (srcImage.format == format)
|
||||
{
|
||||
// Input is already in our required source format
|
||||
return gpubc->Compress(srcImage, destImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert format and then use as the source image
|
||||
ScratchImage image;
|
||||
HRESULT hr;
|
||||
|
||||
DWORD srgb = GetSRGBFlags(compress);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
hr = ConvertToRGBA32(srcImage, image, false, srgb);
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
hr = ConvertToRGBA32(srcImage, image, true, srgb);
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
hr = ConvertToRGBAF32(srcImage, image, srgb);
|
||||
break;
|
||||
|
||||
default:
|
||||
hr = E_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *img = image.GetImage(0, 0, 0);
|
||||
if (!img)
|
||||
return E_POINTER;
|
||||
|
||||
return gpubc->Compress(*img, destImage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================================================
|
||||
// Entry-points
|
||||
@ -198,205 +210,216 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
|
||||
// Compression
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& image )
|
||||
HRESULT DirectX::Compress(
|
||||
ID3D11Device* pDevice,
|
||||
const Image& srcImage,
|
||||
DXGI_FORMAT format,
|
||||
DWORD compress,
|
||||
float alphaWeight,
|
||||
ScratchImage& image)
|
||||
{
|
||||
if ( !pDevice || IsCompressed(srcImage.format) || !IsCompressed(format) )
|
||||
if (!pDevice || IsCompressed(srcImage.format) || !IsCompressed(format))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsTypeless(format)
|
||||
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsTypeless(format)
|
||||
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
// Setup GPU compressor
|
||||
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
|
||||
if ( !gpubc )
|
||||
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
|
||||
if (!gpubc)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
HRESULT hr = gpubc->Initialize( pDevice );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = gpubc->Initialize(pDevice);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = gpubc->Prepare( srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
|
||||
if ( FAILED(hr) )
|
||||
hr = gpubc->Prepare(srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Create workspace for result
|
||||
hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
|
||||
if ( FAILED(hr) )
|
||||
hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *img = image.GetImage( 0, 0, 0 );
|
||||
if ( !img )
|
||||
const Image *img = image.GetImage(0, 0, 0);
|
||||
if (!img)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
hr = _GPUCompress( gpubc.get(), srcImage, *img, compress );
|
||||
if ( FAILED(hr) )
|
||||
hr = GPUCompress(gpubc.get(), srcImage, *img, compress);
|
||||
if (FAILED(hr))
|
||||
image.Release();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
|
||||
DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& cImages )
|
||||
HRESULT DirectX::Compress(
|
||||
ID3D11Device* pDevice,
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DXGI_FORMAT format,
|
||||
DWORD compress,
|
||||
float alphaWeight,
|
||||
ScratchImage& cImages)
|
||||
{
|
||||
if ( !pDevice || !srcImages || !nimages )
|
||||
if (!pDevice || !srcImages || !nimages)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsCompressed(metadata.format) || !IsCompressed(format) )
|
||||
if (IsCompressed(metadata.format) || !IsCompressed(format))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsTypeless(format)
|
||||
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsTypeless(format)
|
||||
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
cImages.Release();
|
||||
|
||||
// Setup GPU compressor
|
||||
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
|
||||
if ( !gpubc )
|
||||
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
|
||||
if (!gpubc)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
HRESULT hr = gpubc->Initialize( pDevice );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = gpubc->Initialize(pDevice);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Create workspace for result
|
||||
TexMetadata mdata2 = metadata;
|
||||
mdata2.format = format;
|
||||
hr = cImages.Initialize( mdata2 );
|
||||
if ( FAILED(hr) )
|
||||
hr = cImages.Initialize(mdata2);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if ( nimages != cImages.GetImageCount() )
|
||||
if (nimages != cImages.GetImageCount())
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const Image* dest = cImages.GetImages();
|
||||
if ( !dest )
|
||||
if (!dest)
|
||||
{
|
||||
cImages.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
// Process images (ordered by size)
|
||||
switch( metadata.dimension )
|
||||
switch (metadata.dimension)
|
||||
{
|
||||
case TEX_DIMENSION_TEXTURE1D:
|
||||
case TEX_DIMENSION_TEXTURE2D:
|
||||
{
|
||||
size_t w = metadata.width;
|
||||
size_t h = metadata.height;
|
||||
{
|
||||
size_t w = metadata.width;
|
||||
size_t h = metadata.height;
|
||||
|
||||
for( size_t level=0; level < metadata.mipLevels; ++level )
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
|
||||
if ( FAILED(hr) )
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (size_t item = 0; item < metadata.arraySize; ++item)
|
||||
{
|
||||
size_t index = metadata.ComputeIndex(level, item, 0);
|
||||
if (index >= nimages)
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
assert(dest[index].format == format);
|
||||
|
||||
const Image& src = srcImages[index];
|
||||
|
||||
if (src.width != dest[index].width || src.height != dest[index].height)
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
for( size_t item = 0; item < metadata.arraySize; ++item )
|
||||
{
|
||||
size_t index = metadata.ComputeIndex( level, item, 0 );
|
||||
if ( index >= nimages )
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
assert( dest[ index ].format == format );
|
||||
|
||||
const Image& src = srcImages[ index ];
|
||||
|
||||
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
if ( h > 1 )
|
||||
h >>= 1;
|
||||
|
||||
if ( w > 1 )
|
||||
w >>= 1;
|
||||
}
|
||||
|
||||
if (h > 1)
|
||||
h >>= 1;
|
||||
|
||||
if (w > 1)
|
||||
w >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEX_DIMENSION_TEXTURE3D:
|
||||
{
|
||||
size_t w = metadata.width;
|
||||
size_t h = metadata.height;
|
||||
size_t d = metadata.depth;
|
||||
{
|
||||
size_t w = metadata.width;
|
||||
size_t h = metadata.height;
|
||||
size_t d = metadata.depth;
|
||||
|
||||
for( size_t level=0; level < metadata.mipLevels; ++level )
|
||||
for (size_t level = 0; level < metadata.mipLevels; ++level)
|
||||
{
|
||||
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
|
||||
if ( FAILED(hr) )
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (size_t slice = 0; slice < d; ++slice)
|
||||
{
|
||||
size_t index = metadata.ComputeIndex(level, 0, slice);
|
||||
if (index >= nimages)
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
assert(dest[index].format == format);
|
||||
|
||||
const Image& src = srcImages[index];
|
||||
|
||||
if (src.width != dest[index].width || src.height != dest[index].height)
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
for( size_t slice=0; slice < d; ++slice )
|
||||
{
|
||||
size_t index = metadata.ComputeIndex( level, 0, slice );
|
||||
if ( index >= nimages )
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
assert( dest[ index ].format == format );
|
||||
|
||||
const Image& src = srcImages[ index ];
|
||||
|
||||
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
|
||||
{
|
||||
cImages.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
cImages.Release();
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
if ( h > 1 )
|
||||
h >>= 1;
|
||||
|
||||
if ( w > 1 )
|
||||
w >>= 1;
|
||||
|
||||
if ( d > 1 )
|
||||
d >>= 1;
|
||||
}
|
||||
|
||||
if (h > 1)
|
||||
h >>= 1;
|
||||
|
||||
if (w > 1)
|
||||
w >>= 1;
|
||||
|
||||
if (d > 1)
|
||||
d >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,110 +15,117 @@
|
||||
|
||||
#include "directxtexp.h"
|
||||
|
||||
using namespace DirectX;
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace DirectX
|
||||
namespace
|
||||
{
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Do flip/rotate operation using WIC
|
||||
//-------------------------------------------------------------------------------------
|
||||
static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWORD flags,
|
||||
_In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
|
||||
{
|
||||
if ( !srcImage.pixels || !destImage.pixels )
|
||||
return E_POINTER;
|
||||
|
||||
assert( srcImage.format == destImage.format );
|
||||
|
||||
bool iswic2 = false;
|
||||
IWICImagingFactory* pWIC = GetWICFactory(iswic2);
|
||||
if ( !pWIC )
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ComPtr<IWICBitmap> source;
|
||||
HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
|
||||
static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
|
||||
srcImage.pixels, source.GetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
ComPtr<IWICBitmapFlipRotator> FR;
|
||||
hr = pWIC->CreateBitmapFlipRotator( FR.GetAddressOf() );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID pfFR;
|
||||
hr = FR->GetPixelFormat( &pfFR );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
if ( memcmp( &pfFR, &pfGUID, sizeof(GUID) ) != 0 )
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Do flip/rotate operation using WIC
|
||||
//-------------------------------------------------------------------------------------
|
||||
HRESULT PerformFlipRotateUsingWIC(
|
||||
const Image& srcImage,
|
||||
DWORD flags,
|
||||
const WICPixelFormatGUID& pfGUID,
|
||||
const Image& destImage)
|
||||
{
|
||||
// Flip/rotate should return the same format as the source...
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (!srcImage.pixels || !destImage.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
assert(srcImage.format == destImage.format);
|
||||
|
||||
bool iswic2 = false;
|
||||
IWICImagingFactory* pWIC = GetWICFactory(iswic2);
|
||||
if (!pWIC)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
ComPtr<IWICBitmap> source;
|
||||
HRESULT hr = pWIC->CreateBitmapFromMemory(static_cast<UINT>(srcImage.width), static_cast<UINT>(srcImage.height), pfGUID,
|
||||
static_cast<UINT>(srcImage.rowPitch), static_cast<UINT>(srcImage.slicePitch),
|
||||
srcImage.pixels, source.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ComPtr<IWICBitmapFlipRotator> FR;
|
||||
hr = pWIC->CreateBitmapFlipRotator(FR.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = FR->Initialize(source.Get(), static_cast<WICBitmapTransformOptions>(flags));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
WICPixelFormatGUID pfFR;
|
||||
hr = FR->GetPixelFormat(&pfFR);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (memcmp(&pfFR, &pfGUID, sizeof(GUID)) != 0)
|
||||
{
|
||||
// Flip/rotate should return the same format as the source...
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
UINT nwidth, nheight;
|
||||
hr = FR->GetSize(&nwidth, &nheight);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (destImage.width != nwidth || destImage.height != nheight)
|
||||
return E_FAIL;
|
||||
|
||||
hr = FR->CopyPixels(0, static_cast<UINT>(destImage.rowPitch), static_cast<UINT>(destImage.slicePitch), destImage.pixels);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UINT nwidth, nheight;
|
||||
hr = FR->GetSize( &nwidth, &nheight );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
if ( destImage.width != nwidth || destImage.height != nheight )
|
||||
return E_FAIL;
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Do conversion, flip/rotate using WIC, conversion cycle
|
||||
//-------------------------------------------------------------------------------------
|
||||
HRESULT PerformFlipRotateViaF32(
|
||||
const Image& srcImage,
|
||||
DWORD flags,
|
||||
const Image& destImage)
|
||||
{
|
||||
if (!srcImage.pixels || !destImage.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
assert(srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT);
|
||||
assert(srcImage.format == destImage.format);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
ScratchImage temp;
|
||||
HRESULT hr = _ConvertToR32G32B32A32(srcImage, temp);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *tsrc = temp.GetImage(0, 0, 0);
|
||||
if (!tsrc)
|
||||
return E_POINTER;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Do conversion, flip/rotate using WIC, conversion cycle
|
||||
//-------------------------------------------------------------------------------------
|
||||
static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
|
||||
{
|
||||
if ( !srcImage.pixels || !destImage.pixels )
|
||||
return E_POINTER;
|
||||
ScratchImage rtemp;
|
||||
hr = rtemp.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
|
||||
assert( srcImage.format == destImage.format );
|
||||
const Image *tdest = rtemp.GetImage(0, 0, 0);
|
||||
if (!tdest)
|
||||
return E_POINTER;
|
||||
|
||||
ScratchImage temp;
|
||||
HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
hr = PerformFlipRotateUsingWIC(*tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *tsrc = temp.GetImage( 0, 0, 0 );
|
||||
if ( !tsrc )
|
||||
return E_POINTER;
|
||||
temp.Release();
|
||||
|
||||
ScratchImage rtemp;
|
||||
hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
hr = _ConvertFromR32G32B32A32(*tdest, destImage);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *tdest = rtemp.GetImage( 0, 0, 0 );
|
||||
if ( !tdest )
|
||||
return E_POINTER;
|
||||
|
||||
hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
|
||||
if ( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
temp.Release();
|
||||
|
||||
hr = _ConvertFromR32G32B32A32( *tdest, destImage );
|
||||
if ( FAILED(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
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
|
||||
HRESULT DirectX::FlipRotate(
|
||||
const Image& srcImage,
|
||||
DWORD flags,
|
||||
ScratchImage& image)
|
||||
{
|
||||
if ( !srcImage.pixels )
|
||||
if (!srcImage.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
if ( !flags )
|
||||
if (!flags)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( (srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX) )
|
||||
if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsCompressed( srcImage.format ) )
|
||||
if (IsCompressed(srcImage.format))
|
||||
{
|
||||
// We don't support flip/rotate operations on compressed images
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
|
||||
static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
|
||||
static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
|
||||
static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
|
||||
static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
|
||||
static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
|
||||
static_assert(TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC");
|
||||
static_assert(TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC");
|
||||
static_assert(TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC");
|
||||
static_assert(TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC");
|
||||
static_assert(TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC");
|
||||
static_assert(TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC");
|
||||
|
||||
// Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
|
||||
switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
|
||||
switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270))
|
||||
{
|
||||
case 0:
|
||||
case TEX_FR_ROTATE90:
|
||||
@ -170,33 +180,33 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
|
||||
size_t nwidth = srcImage.width;
|
||||
size_t nheight = srcImage.height;
|
||||
|
||||
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
|
||||
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
|
||||
{
|
||||
nwidth = srcImage.height;
|
||||
nheight = srcImage.width;
|
||||
}
|
||||
|
||||
HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = image.Initialize2D(srcImage.format, nwidth, nheight, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *rimage = image.GetImage( 0, 0, 0 );
|
||||
if ( !rimage )
|
||||
const Image *rimage = image.GetImage(0, 0, 0);
|
||||
if (!rimage)
|
||||
return E_POINTER;
|
||||
|
||||
WICPixelFormatGUID pfGUID;
|
||||
if ( _DXGIToWIC( srcImage.format, pfGUID ) )
|
||||
if (_DXGIToWIC(srcImage.format, pfGUID))
|
||||
{
|
||||
// Case 1: Source format is supported by Windows Imaging Component
|
||||
hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage );
|
||||
hr = PerformFlipRotateUsingWIC(srcImage, flags, pfGUID, *rimage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
|
||||
hr = _PerformFlipRotateViaF32( srcImage, flags, *rimage );
|
||||
hr = PerformFlipRotateViaF32(srcImage, flags, *rimage);
|
||||
}
|
||||
|
||||
if ( FAILED(hr) )
|
||||
if (FAILED(hr))
|
||||
{
|
||||
image.Release();
|
||||
return hr;
|
||||
@ -210,27 +220,31 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
|
||||
// Flip/rotate image (complex)
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
|
||||
DWORD flags, ScratchImage& result )
|
||||
HRESULT DirectX::FlipRotate(
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DWORD flags,
|
||||
ScratchImage& result)
|
||||
{
|
||||
if ( !srcImages || !nimages )
|
||||
if (!srcImages || !nimages)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsCompressed( metadata.format ) )
|
||||
if (IsCompressed(metadata.format))
|
||||
{
|
||||
// We don't support flip/rotate operations on compressed images
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
|
||||
static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
|
||||
static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
|
||||
static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
|
||||
static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
|
||||
static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
|
||||
static_assert(TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC");
|
||||
static_assert(TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC");
|
||||
static_assert(TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC");
|
||||
static_assert(TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC");
|
||||
static_assert(TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC");
|
||||
static_assert(TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC");
|
||||
|
||||
// Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
|
||||
switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
|
||||
switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270))
|
||||
{
|
||||
case 0:
|
||||
case TEX_FR_ROTATE90:
|
||||
@ -245,51 +259,51 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
||||
TexMetadata mdata2 = metadata;
|
||||
|
||||
bool flipwh = false;
|
||||
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
|
||||
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
|
||||
{
|
||||
flipwh = true;
|
||||
mdata2.width = metadata.height;
|
||||
mdata2.height = metadata.width;
|
||||
}
|
||||
|
||||
HRESULT hr = result.Initialize( mdata2 );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = result.Initialize(mdata2);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if ( nimages != result.GetImageCount() )
|
||||
if (nimages != result.GetImageCount())
|
||||
{
|
||||
result.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const Image* dest = result.GetImages();
|
||||
if ( !dest )
|
||||
if (!dest)
|
||||
{
|
||||
result.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
WICPixelFormatGUID pfGUID;
|
||||
bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
|
||||
bool wicpf = _DXGIToWIC(metadata.format, pfGUID);
|
||||
|
||||
for( size_t index=0; index < nimages; ++index )
|
||||
for (size_t index = 0; index < nimages; ++index)
|
||||
{
|
||||
const Image& src = srcImages[ index ];
|
||||
if ( src.format != metadata.format )
|
||||
const Image& src = srcImages[index];
|
||||
if (src.format != metadata.format)
|
||||
{
|
||||
result.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
|
||||
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
|
||||
return E_FAIL;
|
||||
|
||||
const Image& dst = dest[ index ];
|
||||
assert( dst.format == metadata.format );
|
||||
const Image& dst = dest[index];
|
||||
assert(dst.format == metadata.format);
|
||||
|
||||
if ( flipwh )
|
||||
if (flipwh)
|
||||
{
|
||||
if ( src.width != dst.height || src.height != dst.width )
|
||||
if (src.width != dst.height || src.height != dst.width)
|
||||
{
|
||||
result.Release();
|
||||
return E_FAIL;
|
||||
@ -297,7 +311,7 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( src.width != dst.width || src.height != dst.height )
|
||||
if (src.width != dst.width || src.height != dst.height)
|
||||
{
|
||||
result.Release();
|
||||
return E_FAIL;
|
||||
@ -307,15 +321,15 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
||||
if (wicpf)
|
||||
{
|
||||
// Case 1: Source format is supported by Windows Imaging Component
|
||||
hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst );
|
||||
hr = PerformFlipRotateUsingWIC(src, flags, pfGUID, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
|
||||
hr = _PerformFlipRotateViaF32( src, flags, dst );
|
||||
hr = PerformFlipRotateViaF32(src, flags, dst);
|
||||
}
|
||||
|
||||
if ( FAILED(hr) )
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result.Release();
|
||||
return hr;
|
||||
@ -324,5 +338,3 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,152 +15,158 @@
|
||||
|
||||
#include "directxtexp.h"
|
||||
|
||||
namespace DirectX
|
||||
using namespace DirectX;
|
||||
|
||||
namespace
|
||||
{
|
||||
static const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
|
||||
const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
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 )
|
||||
return E_POINTER;
|
||||
|
||||
assert( image1.width == image2.width && image1.height == image2.height );
|
||||
assert( !IsCompressed( image1.format ) && !IsCompressed( image2.format ) );
|
||||
|
||||
const size_t width = image1.width;
|
||||
|
||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width)*2, 16 ) ) );
|
||||
if ( !scanline )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
// Flags implied from image formats
|
||||
switch( image1.format )
|
||||
//-------------------------------------------------------------------------------------
|
||||
HRESULT ComputeMSE_(
|
||||
const Image& image1,
|
||||
const Image& image2,
|
||||
float& mse,
|
||||
_Out_writes_opt_(4) float* mseV,
|
||||
DWORD flags)
|
||||
{
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
flags |= CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
if (!image1.pixels || !image2.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE1_SRGB | CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
assert(image1.width == image2.width && image1.height == image2.height);
|
||||
assert(!IsCompressed(image1.format) && !IsCompressed(image2.format));
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE1_SRGB;
|
||||
break;
|
||||
}
|
||||
const size_t width = image1.width;
|
||||
|
||||
switch( image2.format )
|
||||
{
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
flags |= CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width) * 2, 16)));
|
||||
if (!scanline)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE2_SRGB | CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE2_SRGB;
|
||||
break;
|
||||
}
|
||||
|
||||
const uint8_t *pSrc1 = image1.pixels;
|
||||
const size_t rowPitch1 = image1.rowPitch;
|
||||
|
||||
const uint8_t *pSrc2 = image2.pixels;
|
||||
const size_t rowPitch2 = image2.rowPitch;
|
||||
|
||||
XMVECTOR acc = g_XMZero;
|
||||
static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
|
||||
|
||||
for( size_t h = 0; h < image1.height; ++h )
|
||||
{
|
||||
XMVECTOR* ptr1 = scanline.get();
|
||||
if ( !_LoadScanline( ptr1, width, pSrc1, rowPitch1, image1.format ) )
|
||||
return E_FAIL;
|
||||
|
||||
XMVECTOR* ptr2 = scanline.get() + width;
|
||||
if ( !_LoadScanline( ptr2, width, pSrc2, rowPitch2, image2.format ) )
|
||||
return E_FAIL;
|
||||
|
||||
for( size_t i = 0; i < width; ++i )
|
||||
// Flags implied from image formats
|
||||
switch (image1.format)
|
||||
{
|
||||
XMVECTOR v1 = *(ptr1++);
|
||||
if ( flags & CMSE_IMAGE1_SRGB )
|
||||
{
|
||||
v1 = XMVectorPow( v1, g_Gamma22 );
|
||||
}
|
||||
if ( flags & CMSE_IMAGE1_X2_BIAS )
|
||||
{
|
||||
v1 = XMVectorMultiplyAdd( v1, two, g_XMNegativeOne );
|
||||
}
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
flags |= CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
|
||||
XMVECTOR v2 = *(ptr2++);
|
||||
if ( flags & CMSE_IMAGE2_SRGB )
|
||||
{
|
||||
v2 = XMVectorPow( v2, g_Gamma22 );
|
||||
}
|
||||
if ( flags & CMSE_IMAGE2_X2_BIAS )
|
||||
{
|
||||
v1 = XMVectorMultiplyAdd( v2, two, g_XMNegativeOne );
|
||||
}
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE1_SRGB | CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
|
||||
// sum[ (I1 - I2)^2 ]
|
||||
XMVECTOR v = XMVectorSubtract( v1, v2 );
|
||||
if ( flags & CMSE_IGNORE_RED )
|
||||
{
|
||||
v = XMVectorSelect( v, g_XMZero, g_XMMaskX );
|
||||
}
|
||||
if ( flags & CMSE_IGNORE_GREEN )
|
||||
{
|
||||
v = XMVectorSelect( v, g_XMZero, g_XMMaskY );
|
||||
}
|
||||
if ( flags & CMSE_IGNORE_BLUE )
|
||||
{
|
||||
v = XMVectorSelect( v, g_XMZero, g_XMMaskZ );
|
||||
}
|
||||
if ( flags & CMSE_IGNORE_ALPHA )
|
||||
{
|
||||
v = XMVectorSelect( v, g_XMZero, g_XMMaskW );
|
||||
}
|
||||
|
||||
acc = XMVectorMultiplyAdd( v, v, acc );
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE1_SRGB;
|
||||
break;
|
||||
}
|
||||
|
||||
pSrc1 += rowPitch1;
|
||||
pSrc2 += rowPitch2;
|
||||
}
|
||||
switch (image2.format)
|
||||
{
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
flags |= CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
|
||||
// MSE = sum[ (I1 - I2)^2 ] / w*h
|
||||
XMVECTOR d = XMVectorReplicate( float(image1.width * image1.height) );
|
||||
XMVECTOR v = XMVectorDivide( acc, d );
|
||||
if ( mseV )
|
||||
{
|
||||
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( mseV ), v );
|
||||
mse = mseV[0] + mseV[1] + mseV[2] + mseV[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
XMFLOAT4 _mseV;
|
||||
XMStoreFloat4( &_mseV, v );
|
||||
mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w;
|
||||
}
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE2_SRGB | CMSE_IGNORE_ALPHA;
|
||||
break;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
flags |= CMSE_IMAGE2_SRGB;
|
||||
break;
|
||||
}
|
||||
|
||||
const uint8_t *pSrc1 = image1.pixels;
|
||||
const size_t rowPitch1 = image1.rowPitch;
|
||||
|
||||
const uint8_t *pSrc2 = image2.pixels;
|
||||
const size_t rowPitch2 = image2.rowPitch;
|
||||
|
||||
XMVECTOR acc = g_XMZero;
|
||||
static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
|
||||
|
||||
for (size_t h = 0; h < image1.height; ++h)
|
||||
{
|
||||
XMVECTOR* ptr1 = scanline.get();
|
||||
if (!_LoadScanline(ptr1, width, pSrc1, rowPitch1, image1.format))
|
||||
return E_FAIL;
|
||||
|
||||
XMVECTOR* ptr2 = scanline.get() + width;
|
||||
if (!_LoadScanline(ptr2, width, pSrc2, rowPitch2, image2.format))
|
||||
return E_FAIL;
|
||||
|
||||
for (size_t i = 0; i < width; ++i)
|
||||
{
|
||||
XMVECTOR v1 = *(ptr1++);
|
||||
if (flags & CMSE_IMAGE1_SRGB)
|
||||
{
|
||||
v1 = XMVectorPow(v1, g_Gamma22);
|
||||
}
|
||||
if (flags & CMSE_IMAGE1_X2_BIAS)
|
||||
{
|
||||
v1 = XMVectorMultiplyAdd(v1, two, g_XMNegativeOne);
|
||||
}
|
||||
|
||||
XMVECTOR v2 = *(ptr2++);
|
||||
if (flags & CMSE_IMAGE2_SRGB)
|
||||
{
|
||||
v2 = XMVectorPow(v2, g_Gamma22);
|
||||
}
|
||||
if (flags & CMSE_IMAGE2_X2_BIAS)
|
||||
{
|
||||
v1 = XMVectorMultiplyAdd(v2, two, g_XMNegativeOne);
|
||||
}
|
||||
|
||||
// sum[ (I1 - I2)^2 ]
|
||||
XMVECTOR v = XMVectorSubtract(v1, v2);
|
||||
if (flags & CMSE_IGNORE_RED)
|
||||
{
|
||||
v = XMVectorSelect(v, g_XMZero, g_XMMaskX);
|
||||
}
|
||||
if (flags & CMSE_IGNORE_GREEN)
|
||||
{
|
||||
v = XMVectorSelect(v, g_XMZero, g_XMMaskY);
|
||||
}
|
||||
if (flags & CMSE_IGNORE_BLUE)
|
||||
{
|
||||
v = XMVectorSelect(v, g_XMZero, g_XMMaskZ);
|
||||
}
|
||||
if (flags & CMSE_IGNORE_ALPHA)
|
||||
{
|
||||
v = XMVectorSelect(v, g_XMZero, g_XMMaskW);
|
||||
}
|
||||
|
||||
acc = XMVectorMultiplyAdd(v, v, acc);
|
||||
}
|
||||
|
||||
pSrc1 += rowPitch1;
|
||||
pSrc2 += rowPitch2;
|
||||
}
|
||||
|
||||
// MSE = sum[ (I1 - I2)^2 ] / w*h
|
||||
XMVECTOR d = XMVectorReplicate(float(image1.width * image1.height));
|
||||
XMVECTOR v = XMVectorDivide(acc, d);
|
||||
if (mseV)
|
||||
{
|
||||
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(mseV), v);
|
||||
mse = mseV[0] + mseV[1] + mseV[2] + mseV[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
XMFLOAT4 _mseV;
|
||||
XMStoreFloat4(&_mseV, v);
|
||||
mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
@ -171,57 +177,63 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
|
||||
// Copies a rectangle from one image into another
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image& dstImage, DWORD filter, size_t xOffset, size_t yOffset )
|
||||
HRESULT DirectX::CopyRectangle(
|
||||
const Image& srcImage,
|
||||
const Rect& srcRect,
|
||||
const Image& dstImage,
|
||||
DWORD filter,
|
||||
size_t xOffset,
|
||||
size_t yOffset)
|
||||
{
|
||||
if ( !srcImage.pixels || !dstImage.pixels )
|
||||
if (!srcImage.pixels || !dstImage.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
if ( IsCompressed( srcImage.format ) || IsCompressed( dstImage.format )
|
||||
|| IsPlanar( srcImage.format ) || IsPlanar( dstImage.format )
|
||||
|| IsPalettized( srcImage.format ) || IsPalettized( dstImage.format ) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsCompressed(srcImage.format) || IsCompressed(dstImage.format)
|
||||
|| IsPlanar(srcImage.format) || IsPlanar(dstImage.format)
|
||||
|| IsPalettized(srcImage.format) || IsPalettized(dstImage.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
// Validate rectangle/offset
|
||||
if ( !srcRect.w || !srcRect.h || ( (srcRect.x + srcRect.w) > srcImage.width ) || ( (srcRect.y + srcRect.h) > srcImage.height ) )
|
||||
if (!srcRect.w || !srcRect.h || ((srcRect.x + srcRect.w) > srcImage.width) || ((srcRect.y + srcRect.h) > srcImage.height))
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if ( ( (xOffset + srcRect.w) > dstImage.width ) || ( (yOffset + srcRect.h) > dstImage.height ) )
|
||||
if (((xOffset + srcRect.w) > dstImage.width) || ((yOffset + srcRect.h) > dstImage.height))
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// Compute source bytes-per-pixel
|
||||
size_t sbpp = BitsPerPixel( srcImage.format );
|
||||
if ( !sbpp )
|
||||
size_t sbpp = BitsPerPixel(srcImage.format);
|
||||
if (!sbpp)
|
||||
return E_FAIL;
|
||||
|
||||
if ( sbpp < 8 )
|
||||
if (sbpp < 8)
|
||||
{
|
||||
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
const uint8_t* pEndSrc = srcImage.pixels + srcImage.rowPitch*srcImage.height;
|
||||
const uint8_t* pEndDest = dstImage.pixels + dstImage.rowPitch*dstImage.height;
|
||||
|
||||
// Round to bytes
|
||||
sbpp = ( sbpp + 7 ) / 8;
|
||||
sbpp = (sbpp + 7) / 8;
|
||||
|
||||
const uint8_t* pSrc = srcImage.pixels + (srcRect.y * srcImage.rowPitch) + (srcRect.x * sbpp);
|
||||
|
||||
if ( srcImage.format == dstImage.format )
|
||||
if (srcImage.format == dstImage.format)
|
||||
{
|
||||
// Direct copy case (avoid intermediate conversions)
|
||||
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * sbpp);
|
||||
const size_t copyW = srcRect.w * sbpp;
|
||||
for( size_t h=0; h < srcRect.h; ++h )
|
||||
for (size_t h = 0; h < srcRect.h; ++h)
|
||||
{
|
||||
if ( ( (pSrc+copyW) > pEndSrc ) || (pDest > pEndDest) )
|
||||
if (((pSrc + copyW) > pEndSrc) || (pDest > pEndDest))
|
||||
return E_FAIL;
|
||||
|
||||
memcpy_s( pDest, pEndDest - pDest, pSrc, copyW );
|
||||
memcpy_s(pDest, pEndDest - pDest, pSrc, copyW);
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += dstImage.rowPitch;
|
||||
@ -231,39 +243,39 @@ HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image&
|
||||
}
|
||||
|
||||
// Compute destination bytes-per-pixel (not the same format as source)
|
||||
size_t dbpp = BitsPerPixel( dstImage.format );
|
||||
if ( !dbpp )
|
||||
size_t dbpp = BitsPerPixel(dstImage.format);
|
||||
if (!dbpp)
|
||||
return E_FAIL;
|
||||
|
||||
if ( dbpp < 8 )
|
||||
if (dbpp < 8)
|
||||
{
|
||||
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
// Round to bytes
|
||||
dbpp = ( dbpp + 7 ) / 8;
|
||||
dbpp = (dbpp + 7) / 8;
|
||||
|
||||
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * dbpp);
|
||||
|
||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcRect.w), 16 ) ) );
|
||||
if ( !scanline )
|
||||
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcRect.w), 16)));
|
||||
if (!scanline)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
const size_t copyS = srcRect.w * sbpp;
|
||||
const size_t copyD = srcRect.w * dbpp;
|
||||
|
||||
for( size_t h=0; h < srcRect.h; ++h )
|
||||
for (size_t h = 0; h < srcRect.h; ++h)
|
||||
{
|
||||
if ( ( (pSrc+copyS) > pEndSrc) || ((pDest+copyD) > pEndDest) )
|
||||
if (((pSrc + copyS) > pEndSrc) || ((pDest + copyD) > pEndDest))
|
||||
return E_FAIL;
|
||||
|
||||
if ( !_LoadScanline( scanline.get(), srcRect.w, pSrc, copyS, srcImage.format ) )
|
||||
if (!_LoadScanline(scanline.get(), srcRect.w, pSrc, copyS, srcImage.format))
|
||||
return E_FAIL;
|
||||
|
||||
_ConvertScanline( scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter );
|
||||
_ConvertScanline(scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter);
|
||||
|
||||
if ( !_StoreScanline( pDest, copyD, dstImage.format, scanline.get(), srcRect.w ) )
|
||||
if (!_StoreScanline(pDest, copyD, dstImage.format, scanline.get(), srcRect.w))
|
||||
return E_FAIL;
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
@ -278,77 +290,80 @@ HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image&
|
||||
// Computes the Mean-Squared-Error (MSE) between two images
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float* mseV, DWORD flags )
|
||||
HRESULT DirectX::ComputeMSE(
|
||||
const Image& image1,
|
||||
const Image& image2,
|
||||
float& mse,
|
||||
float* mseV,
|
||||
DWORD flags)
|
||||
{
|
||||
if ( !image1.pixels || !image2.pixels )
|
||||
if (!image1.pixels || !image2.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
if ( image1.width != image2.width || image1.height != image2.height )
|
||||
if (image1.width != image2.width || image1.height != image2.height)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsPlanar( image1.format ) || IsPlanar( image2.format )
|
||||
|| IsPalettized( image1.format ) || IsPalettized( image2.format ) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsPlanar(image1.format) || IsPlanar(image2.format)
|
||||
|| IsPalettized(image1.format) || IsPalettized(image2.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
if ( IsCompressed(image1.format) )
|
||||
if (IsCompressed(image1.format))
|
||||
{
|
||||
if ( IsCompressed(image2.format) )
|
||||
if (IsCompressed(image2.format))
|
||||
{
|
||||
// Case 1: both images are compressed, expand to RGBA32F
|
||||
ScratchImage temp1;
|
||||
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1 );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ScratchImage temp2;
|
||||
hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2 );
|
||||
if ( FAILED(hr) )
|
||||
hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image* img1 = temp1.GetImage(0,0,0);
|
||||
const Image* img2 = temp2.GetImage(0,0,0);
|
||||
if ( !img1 || !img2 )
|
||||
const Image* img1 = temp1.GetImage(0, 0, 0);
|
||||
const Image* img2 = temp2.GetImage(0, 0, 0);
|
||||
if (!img1 || !img2)
|
||||
return E_POINTER;
|
||||
|
||||
return _ComputeMSE( *img1, *img2, mse, mseV, flags );
|
||||
return ComputeMSE_(*img1, *img2, mse, mseV, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case 2: image1 is compressed, expand to RGBA32F
|
||||
ScratchImage temp;
|
||||
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image* img = temp.GetImage(0,0,0);
|
||||
if ( !img )
|
||||
const Image* img = temp.GetImage(0, 0, 0);
|
||||
if (!img)
|
||||
return E_POINTER;
|
||||
|
||||
return _ComputeMSE( *img, image2, mse, mseV, flags );
|
||||
return ComputeMSE_(*img, image2, mse, mseV, flags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( IsCompressed(image2.format) )
|
||||
if (IsCompressed(image2.format))
|
||||
{
|
||||
// Case 3: image2 is compressed, expand to RGBA32F
|
||||
ScratchImage temp;
|
||||
HRESULT hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image* img = temp.GetImage(0,0,0);
|
||||
if ( !img )
|
||||
const Image* img = temp.GetImage(0, 0, 0);
|
||||
if (!img)
|
||||
return E_POINTER;
|
||||
|
||||
return _ComputeMSE( image1, *img, mse, mseV, flags );
|
||||
return ComputeMSE_(image1, *img, mse, mseV, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case 4: neither image is compressed
|
||||
return _ComputeMSE( image1, image2, mse, mseV, flags );
|
||||
return ComputeMSE_(image1, image2, mse, mseV, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
@ -15,232 +15,238 @@
|
||||
|
||||
#include "directxtexp.h"
|
||||
|
||||
namespace DirectX
|
||||
using namespace DirectX;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
#pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
|
||||
static inline float _EvaluateColor( _In_ FXMVECTOR val, _In_ DWORD flags )
|
||||
{
|
||||
XMFLOAT4A f;
|
||||
|
||||
static XMVECTORF32 lScale = { 0.2125f, 0.7154f, 0.0721f, 1.f };
|
||||
|
||||
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
|
||||
switch( flags & 0xf )
|
||||
inline float EvaluateColor(_In_ FXMVECTOR val, _In_ DWORD flags)
|
||||
{
|
||||
case 0:
|
||||
case CNMAP_CHANNEL_RED: return XMVectorGetX( val );
|
||||
case CNMAP_CHANNEL_GREEN: return XMVectorGetY( val );
|
||||
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ( val );
|
||||
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW( val );
|
||||
XMFLOAT4A f;
|
||||
|
||||
case CNMAP_CHANNEL_LUMINANCE:
|
||||
static XMVECTORF32 lScale = { 0.2125f, 0.7154f, 0.0721f, 1.f };
|
||||
|
||||
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
|
||||
switch (flags & 0xf)
|
||||
{
|
||||
XMVECTOR v = XMVectorMultiply( val, lScale );
|
||||
XMStoreFloat4A( &f, v );
|
||||
case 0:
|
||||
case CNMAP_CHANNEL_RED: return XMVectorGetX(val);
|
||||
case CNMAP_CHANNEL_GREEN: return XMVectorGetY(val);
|
||||
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ(val);
|
||||
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW(val);
|
||||
|
||||
case CNMAP_CHANNEL_LUMINANCE:
|
||||
{
|
||||
XMVECTOR v = XMVectorMultiply(val, lScale);
|
||||
XMStoreFloat4A(&f, v);
|
||||
return f.x + f.y + f.z;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
static void _EvaluateRow( _In_reads_(width) const XMVECTOR* pSource, _Out_writes_(width+2) float* pDest,
|
||||
_In_ size_t width, _In_ DWORD flags )
|
||||
{
|
||||
assert( pSource && pDest );
|
||||
assert( width > 0 );
|
||||
|
||||
for( size_t x = 0; x < width; ++x )
|
||||
{
|
||||
pDest[x+1] = _EvaluateColor( pSource[x], flags );
|
||||
default:
|
||||
assert(false);
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flags & CNMAP_MIRROR_U )
|
||||
void EvaluateRow(
|
||||
_In_reads_(width) const XMVECTOR* pSource,
|
||||
_Out_writes_(width + 2) float* pDest,
|
||||
size_t width,
|
||||
DWORD flags)
|
||||
{
|
||||
// Mirror in U
|
||||
pDest[0] = _EvaluateColor( pSource[0], flags );
|
||||
pDest[width+1] = _EvaluateColor( pSource[width-1], flags );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wrap in U
|
||||
pDest[0] = _EvaluateColor( pSource[width-1], flags );
|
||||
pDest[width+1] = _EvaluateColor( pSource[0], flags );
|
||||
}
|
||||
}
|
||||
assert(pSource && pDest);
|
||||
assert(width > 0);
|
||||
|
||||
static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
|
||||
_In_ DXGI_FORMAT format, _In_ const Image& normalMap )
|
||||
{
|
||||
if ( !srcImage.pixels || !normalMap.pixels )
|
||||
return E_INVALIDARG;
|
||||
|
||||
const DWORD convFlags = _GetConvertFlags( format );
|
||||
if ( !convFlags )
|
||||
return E_FAIL;
|
||||
|
||||
if ( !( convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT) ) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
|
||||
const size_t width = srcImage.width;
|
||||
const size_t height = srcImage.height;
|
||||
if ( width != normalMap.width || height != normalMap.height )
|
||||
return E_FAIL;
|
||||
|
||||
// Allocate temporary space (4 scanlines and 3 evaluated rows)
|
||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*4), 16 ) ) );
|
||||
if ( !scanline )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
ScopedAlignedArrayFloat buffer( reinterpret_cast<float*>( _aligned_malloc( ( ( sizeof(float) * ( width + 2 ) ) * 3 ), 16 ) ) );
|
||||
if ( !buffer )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
uint8_t* pDest = normalMap.pixels;
|
||||
if ( !pDest )
|
||||
return E_POINTER;
|
||||
|
||||
XMVECTOR* row0 = scanline.get();
|
||||
XMVECTOR* row1 = row0 + width;
|
||||
XMVECTOR* row2 = row1 + width;
|
||||
XMVECTOR* target = row2 + width;
|
||||
|
||||
float* val0 = buffer.get();
|
||||
float* val1 = val0 + width + 2;
|
||||
float* val2 = val1 + width + 2;
|
||||
|
||||
const size_t rowPitch = srcImage.rowPitch;
|
||||
const uint8_t* pSrc = srcImage.pixels;
|
||||
|
||||
// Read first scanline row into 'row1'
|
||||
if ( !_LoadScanline( row1, width, pSrc, rowPitch, srcImage.format ) )
|
||||
return E_FAIL;
|
||||
|
||||
// Setup 'row0'
|
||||
if ( flags & CNMAP_MIRROR_V )
|
||||
{
|
||||
// Mirror first row
|
||||
memcpy_s( row0, rowPitch, row1, rowPitch );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read last row (Wrap V)
|
||||
if ( !_LoadScanline( row0, width, pSrc + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Evaluate the initial rows
|
||||
_EvaluateRow( row0, val0, width, flags );
|
||||
_EvaluateRow( row1, val1, width, flags );
|
||||
|
||||
pSrc += rowPitch;
|
||||
|
||||
for( size_t y = 0; y < height; ++y )
|
||||
{
|
||||
// Load next scanline of source image
|
||||
if ( y < (height-1) )
|
||||
for (size_t x = 0; x < width; ++x)
|
||||
{
|
||||
if ( !_LoadScanline( row2, width, pSrc, rowPitch, srcImage.format ) )
|
||||
return E_FAIL;
|
||||
pDest[x + 1] = EvaluateColor(pSource[x], flags);
|
||||
}
|
||||
|
||||
if (flags & CNMAP_MIRROR_U)
|
||||
{
|
||||
// Mirror in U
|
||||
pDest[0] = EvaluateColor(pSource[0], flags);
|
||||
pDest[width + 1] = EvaluateColor(pSource[width - 1], flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( flags & CNMAP_MIRROR_V )
|
||||
// Wrap in U
|
||||
pDest[0] = EvaluateColor(pSource[width - 1], flags);
|
||||
pDest[width + 1] = EvaluateColor(pSource[0], flags);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT ComputeNMap(_In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
|
||||
_In_ DXGI_FORMAT format, _In_ const Image& normalMap)
|
||||
{
|
||||
if (!srcImage.pixels || !normalMap.pixels)
|
||||
return E_INVALIDARG;
|
||||
|
||||
const DWORD convFlags = _GetConvertFlags(format);
|
||||
if (!convFlags)
|
||||
return E_FAIL;
|
||||
|
||||
if (!(convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT)))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
const size_t width = srcImage.width;
|
||||
const size_t height = srcImage.height;
|
||||
if (width != normalMap.width || height != normalMap.height)
|
||||
return E_FAIL;
|
||||
|
||||
// Allocate temporary space (4 scanlines and 3 evaluated rows)
|
||||
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width * 4), 16)));
|
||||
if (!scanline)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
ScopedAlignedArrayFloat buffer(reinterpret_cast<float*>(_aligned_malloc(((sizeof(float) * (width + 2)) * 3), 16)));
|
||||
if (!buffer)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
uint8_t* pDest = normalMap.pixels;
|
||||
if (!pDest)
|
||||
return E_POINTER;
|
||||
|
||||
XMVECTOR* row0 = scanline.get();
|
||||
XMVECTOR* row1 = row0 + width;
|
||||
XMVECTOR* row2 = row1 + width;
|
||||
XMVECTOR* target = row2 + width;
|
||||
|
||||
float* val0 = buffer.get();
|
||||
float* val1 = val0 + width + 2;
|
||||
float* val2 = val1 + width + 2;
|
||||
|
||||
const size_t rowPitch = srcImage.rowPitch;
|
||||
const uint8_t* pSrc = srcImage.pixels;
|
||||
|
||||
// Read first scanline row into 'row1'
|
||||
if (!_LoadScanline(row1, width, pSrc, rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
|
||||
// Setup 'row0'
|
||||
if (flags & CNMAP_MIRROR_V)
|
||||
{
|
||||
// Mirror first row
|
||||
memcpy_s(row0, rowPitch, row1, rowPitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read last row (Wrap V)
|
||||
if (!_LoadScanline(row0, width, pSrc + (rowPitch * (height - 1)), rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Evaluate the initial rows
|
||||
EvaluateRow(row0, val0, width, flags);
|
||||
EvaluateRow(row1, val1, width, flags);
|
||||
|
||||
pSrc += rowPitch;
|
||||
|
||||
for (size_t y = 0; y < height; ++y)
|
||||
{
|
||||
// Load next scanline of source image
|
||||
if (y < (height - 1))
|
||||
{
|
||||
// Use last row of source image
|
||||
if ( !_LoadScanline( row2, width, srcImage.pixels + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
|
||||
if (!_LoadScanline(row2, width, pSrc, rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use first row of source image (Wrap V)
|
||||
if ( !_LoadScanline( row2, width, srcImage.pixels, rowPitch, srcImage.format ) )
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate row
|
||||
_EvaluateRow( row2, val2, width, flags );
|
||||
|
||||
// Generate target scanline
|
||||
XMVECTOR *dptr = target;
|
||||
for( size_t x = 0; x < width; ++x )
|
||||
{
|
||||
// Compute normal via central differencing
|
||||
float totDelta = ( val0[x] - val0[x+2] ) + ( val1[x] - val1[x+2] ) + ( val2[x] - val2[x+2] );
|
||||
float deltaZX = totDelta * amplitude / 6.f;
|
||||
|
||||
totDelta = ( val0[x] - val2[x] ) + ( val0[x+1] - val2[x+1] ) + ( val0[x+2] - val2[x+2] );
|
||||
float deltaZY = totDelta * amplitude / 6.f;
|
||||
|
||||
XMVECTOR vx = XMVectorSetZ( g_XMNegIdentityR0, deltaZX ); // (-1.0f, 0.0f, deltaZX)
|
||||
XMVECTOR vy = XMVectorSetZ( g_XMNegIdentityR1, deltaZY ); // (0.0f, -1.0f, deltaZY)
|
||||
|
||||
XMVECTOR normal = XMVector3Normalize( XMVector3Cross( vx, vy ) );
|
||||
|
||||
// Compute alpha (1.0 or an occlusion term)
|
||||
float alpha = 1.f;
|
||||
|
||||
if ( flags & CNMAP_COMPUTE_OCCLUSION )
|
||||
{
|
||||
float delta = 0.f;
|
||||
float c = val1[x+1];
|
||||
|
||||
float t = val0[x] - c; if ( t > 0.f ) delta += t;
|
||||
t = val0[x+1] - c; if ( t > 0.f ) delta += t;
|
||||
t = val0[x+2] - c; if ( t > 0.f ) delta += t;
|
||||
t = val1[x] - c; if ( t > 0.f ) delta += t;
|
||||
// Skip current pixel
|
||||
t = val1[x+2] - c; if ( t > 0.f ) delta += t;
|
||||
t = val2[x] - c; if ( t > 0.f ) delta += t;
|
||||
t = val2[x+1] - c; if ( t > 0.f ) delta += t;
|
||||
t = val2[x+2] - c; if ( t > 0.f ) delta += t;
|
||||
|
||||
// Average delta (divide by 8, scale by amplitude factor)
|
||||
delta *= 0.125f * amplitude;
|
||||
if ( delta > 0.f )
|
||||
if (flags & CNMAP_MIRROR_V)
|
||||
{
|
||||
// If < 0, then no occlusion
|
||||
float r = sqrtf( 1.f + delta*delta );
|
||||
alpha = (r - delta) / r;
|
||||
// Use last row of source image
|
||||
if (!_LoadScanline(row2, width, srcImage.pixels + (rowPitch * (height - 1)), rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use first row of source image (Wrap V)
|
||||
if (!_LoadScanline(row2, width, srcImage.pixels, rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Encode based on target format
|
||||
if ( convFlags & CONVF_UNORM )
|
||||
// Evaluate row
|
||||
EvaluateRow(row2, val2, width, flags);
|
||||
|
||||
// Generate target scanline
|
||||
XMVECTOR *dptr = target;
|
||||
for (size_t x = 0; x < width; ++x)
|
||||
{
|
||||
// 0.5f*normal + 0.5f -or- invert sign case: -0.5f*normal + 0.5f
|
||||
XMVECTOR n1 = XMVectorMultiplyAdd( (flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf );
|
||||
*dptr++ = XMVectorSetW( n1, alpha );
|
||||
}
|
||||
else if ( flags & CNMAP_INVERT_SIGN )
|
||||
{
|
||||
*dptr++ = XMVectorSetW( XMVectorNegate( normal ), alpha );
|
||||
}
|
||||
else
|
||||
{
|
||||
*dptr++ = XMVectorSetW( normal, alpha );
|
||||
// Compute normal via central differencing
|
||||
float totDelta = (val0[x] - val0[x + 2]) + (val1[x] - val1[x + 2]) + (val2[x] - val2[x + 2]);
|
||||
float deltaZX = totDelta * amplitude / 6.f;
|
||||
|
||||
totDelta = (val0[x] - val2[x]) + (val0[x + 1] - val2[x + 1]) + (val0[x + 2] - val2[x + 2]);
|
||||
float deltaZY = totDelta * amplitude / 6.f;
|
||||
|
||||
XMVECTOR vx = XMVectorSetZ(g_XMNegIdentityR0, deltaZX); // (-1.0f, 0.0f, deltaZX)
|
||||
XMVECTOR vy = XMVectorSetZ(g_XMNegIdentityR1, deltaZY); // (0.0f, -1.0f, deltaZY)
|
||||
|
||||
XMVECTOR normal = XMVector3Normalize(XMVector3Cross(vx, vy));
|
||||
|
||||
// Compute alpha (1.0 or an occlusion term)
|
||||
float alpha = 1.f;
|
||||
|
||||
if (flags & CNMAP_COMPUTE_OCCLUSION)
|
||||
{
|
||||
float delta = 0.f;
|
||||
float c = val1[x + 1];
|
||||
|
||||
float t = val0[x] - c; if (t > 0.f) delta += t;
|
||||
t = val0[x + 1] - c; if (t > 0.f) delta += t;
|
||||
t = val0[x + 2] - c; if (t > 0.f) delta += t;
|
||||
t = val1[x] - c; if (t > 0.f) delta += t;
|
||||
// Skip current pixel
|
||||
t = val1[x + 2] - c; if (t > 0.f) delta += t;
|
||||
t = val2[x] - c; if (t > 0.f) delta += t;
|
||||
t = val2[x + 1] - c; if (t > 0.f) delta += t;
|
||||
t = val2[x + 2] - c; if (t > 0.f) delta += t;
|
||||
|
||||
// Average delta (divide by 8, scale by amplitude factor)
|
||||
delta *= 0.125f * amplitude;
|
||||
if (delta > 0.f)
|
||||
{
|
||||
// If < 0, then no occlusion
|
||||
float r = sqrtf(1.f + delta*delta);
|
||||
alpha = (r - delta) / r;
|
||||
}
|
||||
}
|
||||
|
||||
// Encode based on target format
|
||||
if (convFlags & CONVF_UNORM)
|
||||
{
|
||||
// 0.5f*normal + 0.5f -or- invert sign case: -0.5f*normal + 0.5f
|
||||
XMVECTOR n1 = XMVectorMultiplyAdd((flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf);
|
||||
*dptr++ = XMVectorSetW(n1, alpha);
|
||||
}
|
||||
else if (flags & CNMAP_INVERT_SIGN)
|
||||
{
|
||||
*dptr++ = XMVectorSetW(XMVectorNegate(normal), alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dptr++ = XMVectorSetW(normal, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_StoreScanline(pDest, normalMap.rowPitch, format, target, width))
|
||||
return E_FAIL;
|
||||
|
||||
// Cycle buffers
|
||||
float* temp = val0;
|
||||
val0 = val1;
|
||||
val1 = val2;
|
||||
val2 = temp;
|
||||
|
||||
pSrc += rowPitch;
|
||||
pDest += normalMap.rowPitch;
|
||||
}
|
||||
|
||||
if ( !_StoreScanline( pDest, normalMap.rowPitch, format, target, width ) )
|
||||
return E_FAIL;
|
||||
|
||||
// Cycle buffers
|
||||
float* temp = val0;
|
||||
val0 = val1;
|
||||
val1 = val2;
|
||||
val2 = temp;
|
||||
|
||||
pSrc += rowPitch;
|
||||
pDest += normalMap.rowPitch;
|
||||
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
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
|
||||
DXGI_FORMAT format, ScratchImage& normalMap )
|
||||
HRESULT DirectX::ComputeNormalMap(
|
||||
const Image& srcImage,
|
||||
DWORD flags,
|
||||
float amplitude,
|
||||
DXGI_FORMAT format,
|
||||
ScratchImage& normalMap)
|
||||
{
|
||||
if ( !srcImage.pixels || !IsValid(format) )
|
||||
if (!srcImage.pixels || !IsValid(format))
|
||||
return E_INVALIDARG;
|
||||
|
||||
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
|
||||
switch( flags & 0xf )
|
||||
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
|
||||
switch (flags & 0xf)
|
||||
{
|
||||
case 0:
|
||||
case CNMAP_CHANNEL_RED:
|
||||
@ -273,28 +283,28 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if ( IsCompressed(format) || IsCompressed(srcImage.format)
|
||||
|| IsTypeless(format) || IsTypeless(srcImage.format)
|
||||
|| IsPlanar(format) || IsPlanar(srcImage.format)
|
||||
|| IsPalettized(format) || IsPalettized(srcImage.format) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsCompressed(format) || IsCompressed(srcImage.format)
|
||||
|| IsTypeless(format) || IsTypeless(srcImage.format)
|
||||
|| IsPlanar(format) || IsPlanar(srcImage.format)
|
||||
|| IsPalettized(format) || IsPalettized(srcImage.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
// Setup target image
|
||||
normalMap.Release();
|
||||
|
||||
HRESULT hr = normalMap.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = normalMap.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *img = normalMap.GetImage( 0, 0, 0 );
|
||||
if ( !img )
|
||||
const Image *img = normalMap.GetImage(0, 0, 0);
|
||||
if (!img)
|
||||
{
|
||||
normalMap.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
hr = _ComputeNMap( srcImage, flags, amplitude, format, *img );
|
||||
if ( FAILED(hr) )
|
||||
hr = ComputeNMap(srcImage, flags, amplitude, format, *img);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
normalMap.Release();
|
||||
return hr;
|
||||
@ -304,20 +314,26 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
|
||||
DWORD flags, float amplitude, DXGI_FORMAT format, ScratchImage& normalMaps )
|
||||
HRESULT DirectX::ComputeNormalMap(
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DWORD flags,
|
||||
float amplitude,
|
||||
DXGI_FORMAT format,
|
||||
ScratchImage& normalMaps)
|
||||
{
|
||||
if ( !srcImages || !nimages || !IsValid(format) )
|
||||
if (!srcImages || !nimages || !IsValid(format))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsCompressed(format) || IsCompressed(metadata.format)
|
||||
|| IsTypeless(format) || IsTypeless(metadata.format)
|
||||
|| IsPlanar(format) || IsPlanar(metadata.format)
|
||||
|| IsPalettized(format) || IsPalettized(metadata.format) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsCompressed(format) || IsCompressed(metadata.format)
|
||||
|| IsTypeless(format) || IsTypeless(metadata.format)
|
||||
|| IsPlanar(format) || IsPlanar(metadata.format)
|
||||
|| IsPalettized(format) || IsPalettized(metadata.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
|
||||
switch( flags & 0xf )
|
||||
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
|
||||
switch (flags & 0xf)
|
||||
{
|
||||
case 0:
|
||||
case CNMAP_CHANNEL_RED:
|
||||
@ -335,42 +351,42 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
|
||||
|
||||
TexMetadata mdata2 = metadata;
|
||||
mdata2.format = format;
|
||||
HRESULT hr = normalMaps.Initialize( mdata2 );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = normalMaps.Initialize(mdata2);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if ( nimages != normalMaps.GetImageCount() )
|
||||
if (nimages != normalMaps.GetImageCount())
|
||||
{
|
||||
normalMaps.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const Image* dest = normalMaps.GetImages();
|
||||
if ( !dest )
|
||||
if (!dest)
|
||||
{
|
||||
normalMaps.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
for( size_t index=0; index < nimages; ++index )
|
||||
for (size_t index = 0; index < nimages; ++index)
|
||||
{
|
||||
assert( dest[ index ].format == format );
|
||||
assert(dest[index].format == format);
|
||||
|
||||
const Image& src = srcImages[ index ];
|
||||
if ( IsCompressed( src.format ) || IsTypeless( src.format ) )
|
||||
const Image& src = srcImages[index];
|
||||
if (IsCompressed(src.format) || IsTypeless(src.format))
|
||||
{
|
||||
normalMaps.Release();
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
|
||||
if (src.width != dest[index].width || src.height != dest[index].height)
|
||||
{
|
||||
normalMaps.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = _ComputeNMap( src, flags, amplitude, format, dest[ index ] );
|
||||
if ( FAILED(hr) )
|
||||
hr = ComputeNMap(src, flags, amplitude, format, dest[index]);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
normalMaps.Release();
|
||||
return hr;
|
||||
@ -379,5 +395,3 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
@ -175,40 +175,40 @@ namespace DirectX
|
||||
|
||||
void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
|
||||
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
|
||||
LPVOID pDestination, _In_ size_t outSize,
|
||||
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
|
||||
void* pDestination, _In_ size_t outSize,
|
||||
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
|
||||
_In_ DXGI_FORMAT format, _In_ DWORD flags );
|
||||
|
||||
void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_)
|
||||
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
|
||||
LPVOID pDestination, _In_ size_t outSize,
|
||||
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
|
||||
void* pDestination, _In_ size_t outSize,
|
||||
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
|
||||
_In_ DXGI_FORMAT format, _In_ DWORD flags );
|
||||
|
||||
_Success_(return != false)
|
||||
bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize,
|
||||
bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) void* pDestination, _In_ size_t outSize,
|
||||
_In_ DXGI_FORMAT outFormat,
|
||||
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
|
||||
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
|
||||
_In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
|
||||
|
||||
_Success_(return != false)
|
||||
bool __cdecl _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
|
||||
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
|
||||
_In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
|
||||
|
||||
_Success_(return != false)
|
||||
bool __cdecl _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
|
||||
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
|
||||
_In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
|
||||
|
||||
_Success_(return != false)
|
||||
bool __cdecl _StoreScanline( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
|
||||
bool __cdecl _StoreScanline( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
|
||||
_In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0 );
|
||||
|
||||
_Success_(return != false)
|
||||
bool __cdecl _StoreScanlineLinear( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
|
||||
bool __cdecl _StoreScanlineLinear( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
|
||||
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags, _In_ float threshold = 0 );
|
||||
|
||||
_Success_(return != false)
|
||||
bool __cdecl _StoreScanlineDither( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
|
||||
bool __cdecl _StoreScanlineDither( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
|
||||
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ float threshold, size_t y, size_t z,
|
||||
_Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors );
|
||||
|
||||
@ -225,6 +225,6 @@ namespace DirectX
|
||||
//---------------------------------------------------------------------------------
|
||||
// DDS helper functions
|
||||
HRESULT __cdecl _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
|
||||
_Out_writes_bytes_to_opt_(maxsize, required) LPVOID pDestination, _In_ size_t maxsize, _Out_ size_t& required );
|
||||
_Out_writes_bytes_to_opt_(maxsize, required) void* pDestination, _In_ size_t maxsize, _Out_ size_t& required );
|
||||
|
||||
}; // namespace
|
||||
|
@ -15,88 +15,91 @@
|
||||
|
||||
#include "directxtexp.h"
|
||||
|
||||
namespace DirectX
|
||||
using namespace DirectX;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& destImage )
|
||||
{
|
||||
assert( srcImage.width == destImage.width );
|
||||
assert( srcImage.height == destImage.height );
|
||||
|
||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
|
||||
if ( !scanline )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
uint8_t *pDest = destImage.pixels;
|
||||
if ( !pSrc || !pDest )
|
||||
return E_POINTER;
|
||||
|
||||
for( size_t h = 0; h < srcImage.height; ++h )
|
||||
HRESULT PremultiplyAlpha_(const Image& srcImage, const Image& destImage)
|
||||
{
|
||||
if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
|
||||
return E_FAIL;
|
||||
assert(srcImage.width == destImage.width);
|
||||
assert(srcImage.height == destImage.height);
|
||||
|
||||
XMVECTOR* ptr = scanline.get();
|
||||
for( size_t w = 0; w < srcImage.width; ++w )
|
||||
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
|
||||
if (!scanline)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
uint8_t *pDest = destImage.pixels;
|
||||
if (!pSrc || !pDest)
|
||||
return E_POINTER;
|
||||
|
||||
for (size_t h = 0; h < srcImage.height; ++h)
|
||||
{
|
||||
XMVECTOR v = *ptr;
|
||||
XMVECTOR alpha = XMVectorSplatW( *ptr );
|
||||
alpha = XMVectorMultiply( v, alpha );
|
||||
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
|
||||
if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
|
||||
return E_FAIL;
|
||||
|
||||
XMVECTOR* ptr = scanline.get();
|
||||
for (size_t w = 0; w < srcImage.width; ++w)
|
||||
{
|
||||
XMVECTOR v = *ptr;
|
||||
XMVECTOR alpha = XMVectorSplatW(*ptr);
|
||||
alpha = XMVectorMultiply(v, alpha);
|
||||
*(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110);
|
||||
}
|
||||
|
||||
if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width))
|
||||
return E_FAIL;
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += destImage.rowPitch;
|
||||
}
|
||||
|
||||
if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
|
||||
return E_FAIL;
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += destImage.rowPitch;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
|
||||
{
|
||||
assert( srcImage.width == destImage.width );
|
||||
assert( srcImage.height == destImage.height );
|
||||
|
||||
static_assert( TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
|
||||
static_assert( TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
|
||||
static_assert( TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
|
||||
flags &= TEX_PMALPHA_SRGB;
|
||||
|
||||
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
|
||||
if ( !scanline )
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
uint8_t *pDest = destImage.pixels;
|
||||
if ( !pSrc || !pDest )
|
||||
return E_POINTER;
|
||||
|
||||
for( size_t h = 0; h < srcImage.height; ++h )
|
||||
HRESULT PremultiplyAlphaLinear(const Image& srcImage, DWORD flags, const Image& destImage)
|
||||
{
|
||||
if ( !_LoadScanlineLinear( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags ) )
|
||||
return E_FAIL;
|
||||
assert(srcImage.width == destImage.width);
|
||||
assert(srcImage.height == destImage.height);
|
||||
|
||||
XMVECTOR* ptr = scanline.get();
|
||||
for( size_t w = 0; w < srcImage.width; ++w )
|
||||
static_assert(TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
|
||||
static_assert(TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
|
||||
static_assert(TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
|
||||
flags &= TEX_PMALPHA_SRGB;
|
||||
|
||||
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
|
||||
if (!scanline)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
const uint8_t *pSrc = srcImage.pixels;
|
||||
uint8_t *pDest = destImage.pixels;
|
||||
if (!pSrc || !pDest)
|
||||
return E_POINTER;
|
||||
|
||||
for (size_t h = 0; h < srcImage.height; ++h)
|
||||
{
|
||||
XMVECTOR v = *ptr;
|
||||
XMVECTOR alpha = XMVectorSplatW( *ptr );
|
||||
alpha = XMVectorMultiply( v, alpha );
|
||||
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
|
||||
if (!_LoadScanlineLinear(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags))
|
||||
return E_FAIL;
|
||||
|
||||
XMVECTOR* ptr = scanline.get();
|
||||
for (size_t w = 0; w < srcImage.width; ++w)
|
||||
{
|
||||
XMVECTOR v = *ptr;
|
||||
XMVECTOR alpha = XMVectorSplatW(*ptr);
|
||||
alpha = XMVectorMultiply(v, alpha);
|
||||
*(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110);
|
||||
}
|
||||
|
||||
if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags))
|
||||
return E_FAIL;
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += destImage.rowPitch;
|
||||
}
|
||||
|
||||
if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags ) )
|
||||
return E_FAIL;
|
||||
|
||||
pSrc += srcImage.rowPitch;
|
||||
pDest += destImage.rowPitch;
|
||||
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
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image )
|
||||
HRESULT DirectX::PremultiplyAlpha(
|
||||
const Image& srcImage,
|
||||
DWORD flags,
|
||||
ScratchImage& image)
|
||||
{
|
||||
if ( !srcImage.pixels )
|
||||
if (!srcImage.pixels)
|
||||
return E_POINTER;
|
||||
|
||||
if ( IsCompressed(srcImage.format)
|
||||
|| IsPlanar(srcImage.format)
|
||||
|| IsPalettized(srcImage.format)
|
||||
|| IsTypeless(srcImage.format)
|
||||
|| !HasAlpha(srcImage.format) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsCompressed(srcImage.format)
|
||||
|| IsPlanar(srcImage.format)
|
||||
|| IsPalettized(srcImage.format)
|
||||
|| IsTypeless(srcImage.format)
|
||||
|| !HasAlpha(srcImage.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
if ( (srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX) )
|
||||
if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX))
|
||||
return E_INVALIDARG;
|
||||
|
||||
HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
const Image *rimage = image.GetImage( 0, 0, 0 );
|
||||
if ( !rimage )
|
||||
const Image *rimage = image.GetImage(0, 0, 0);
|
||||
if (!rimage)
|
||||
{
|
||||
image.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( srcImage, *rimage ) : _PremultiplyAlphaLinear( srcImage, flags, *rimage );
|
||||
if ( FAILED(hr) )
|
||||
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(srcImage, *rimage) : PremultiplyAlphaLinear(srcImage, flags, *rimage);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
image.Release();
|
||||
return hr;
|
||||
@ -149,22 +155,27 @@ HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& imag
|
||||
// Converts to a premultiplied alpha version of the texture (complex)
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result )
|
||||
HRESULT DirectX::PremultiplyAlpha(
|
||||
const Image* srcImages,
|
||||
size_t nimages,
|
||||
const TexMetadata& metadata,
|
||||
DWORD flags,
|
||||
ScratchImage& result)
|
||||
{
|
||||
if ( !srcImages || !nimages )
|
||||
if (!srcImages || !nimages)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( IsCompressed(metadata.format)
|
||||
|| IsPlanar(metadata.format)
|
||||
|| IsPalettized(metadata.format)
|
||||
|| IsTypeless(metadata.format)
|
||||
|| !HasAlpha(metadata.format) )
|
||||
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
|
||||
if (IsCompressed(metadata.format)
|
||||
|| IsPlanar(metadata.format)
|
||||
|| IsPalettized(metadata.format)
|
||||
|| IsTypeless(metadata.format)
|
||||
|| !HasAlpha(metadata.format))
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
|
||||
if ( (metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX) )
|
||||
if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if ( metadata.IsPMAlpha() )
|
||||
if (metadata.IsPMAlpha())
|
||||
{
|
||||
// Already premultiplied
|
||||
return E_FAIL;
|
||||
@ -172,46 +183,46 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
|
||||
|
||||
TexMetadata mdata2 = metadata;
|
||||
mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED);
|
||||
HRESULT hr = result.Initialize( mdata2 );
|
||||
if ( FAILED(hr) )
|
||||
HRESULT hr = result.Initialize(mdata2);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if ( nimages != result.GetImageCount() )
|
||||
if (nimages != result.GetImageCount())
|
||||
{
|
||||
result.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const Image* dest = result.GetImages();
|
||||
if ( !dest )
|
||||
if (!dest)
|
||||
{
|
||||
result.Release();
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
for( size_t index=0; index < nimages; ++index )
|
||||
for (size_t index = 0; index < nimages; ++index)
|
||||
{
|
||||
const Image& src = srcImages[ index ];
|
||||
if ( src.format != metadata.format )
|
||||
const Image& src = srcImages[index];
|
||||
if (src.format != metadata.format)
|
||||
{
|
||||
result.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
|
||||
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
|
||||
return E_FAIL;
|
||||
|
||||
const Image& dst = dest[ index ];
|
||||
assert( dst.format == metadata.format );
|
||||
const Image& dst = dest[index];
|
||||
assert(dst.format == metadata.format);
|
||||
|
||||
if ( src.width != dst.width || src.height != dst.height )
|
||||
if (src.width != dst.width || src.height != dst.height)
|
||||
{
|
||||
result.Release();
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( src, dst ) : _PremultiplyAlphaLinear( src, flags, dst );
|
||||
if ( FAILED(hr) )
|
||||
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(src, dst) : PremultiplyAlphaLinear(src, flags, dst);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result.Release();
|
||||
return hr;
|
||||
@ -220,5 +231,3 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,8 +15,6 @@
|
||||
|
||||
#include "directxtexp.h"
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
#if defined(_XBOX_ONE) && defined(_TITLE)
|
||||
static_assert(XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT == DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT, "Xbox One XDK mismatch detected");
|
||||
static_assert(XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT == DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT, "Xbox One XDK mismatch detected");
|
||||
@ -33,68 +31,70 @@ static_assert(WIN10_DXGI_FORMAT_V208 == DXGI_FORMAT_V208, "Windows SDK mismatch
|
||||
static_assert(WIN10_DXGI_FORMAT_V408 == DXGI_FORMAT_V408, "Windows SDK mismatch detected");
|
||||
#endif
|
||||
|
||||
using namespace DirectX;
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format Translation Data
|
||||
//-------------------------------------------------------------------------------------
|
||||
struct WICTranslate
|
||||
namespace
|
||||
{
|
||||
GUID wic;
|
||||
DXGI_FORMAT format;
|
||||
bool srgb;
|
||||
};
|
||||
//-------------------------------------------------------------------------------------
|
||||
// WIC Pixel Format Translation Data
|
||||
//-------------------------------------------------------------------------------------
|
||||
struct WICTranslate
|
||||
{
|
||||
GUID wic;
|
||||
DXGI_FORMAT format;
|
||||
bool srgb;
|
||||
};
|
||||
|
||||
static const WICTranslate g_WICFormats[] =
|
||||
{
|
||||
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
|
||||
const WICTranslate g_WICFormats[] =
|
||||
{
|
||||
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
|
||||
|
||||
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false },
|
||||
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM, true },
|
||||
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false },
|
||||
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM, true },
|
||||
|
||||
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM, true },
|
||||
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM, true }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM, true }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM, true },
|
||||
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM, true }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM, true }, // DXGI 1.1
|
||||
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM, true },
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true }, // DXGI 1.1
|
||||
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM, true },
|
||||
|
||||
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM, true },
|
||||
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM, true },
|
||||
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM, true },
|
||||
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM, true },
|
||||
|
||||
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT, false },
|
||||
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT, false },
|
||||
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM, true },
|
||||
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM, true },
|
||||
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT, false },
|
||||
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT, false },
|
||||
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM, true },
|
||||
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM, true },
|
||||
|
||||
{ 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;
|
||||
static IWICImagingFactory* g_Factory = nullptr;
|
||||
bool g_WIC2 = false;
|
||||
IWICImagingFactory* g_Factory = nullptr;
|
||||
}
|
||||
|
||||
|
||||
namespace DirectX
|
||||
{
|
||||
|
||||
//=====================================================================================
|
||||
// WIC Utilities
|
||||
//=====================================================================================
|
||||
|
||||
_Use_decl_annotations_
|
||||
DXGI_FORMAT _WICToDXGI( const GUID& guid )
|
||||
DXGI_FORMAT DirectX::_WICToDXGI(const GUID& guid)
|
||||
{
|
||||
for( size_t i=0; i < _countof(g_WICFormats); ++i )
|
||||
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
|
||||
{
|
||||
if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 )
|
||||
if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
|
||||
return g_WICFormats[i].format;
|
||||
}
|
||||
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
if ( g_WIC2 )
|
||||
if (g_WIC2)
|
||||
{
|
||||
if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 )
|
||||
if (memcmp(&GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID)) == 0)
|
||||
return DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
}
|
||||
#endif
|
||||
@ -103,7 +103,7 @@ DXGI_FORMAT _WICToDXGI( const GUID& guid )
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
|
||||
bool DirectX::_DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
|
||||
{
|
||||
switch( format )
|
||||
{
|
||||
@ -163,28 +163,28 @@ bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID )
|
||||
DWORD DirectX::_CheckWICColorSpace(_In_ const GUID& sourceGUID, _In_ const GUID& targetGUID)
|
||||
{
|
||||
DWORD srgb = 0;
|
||||
|
||||
for( size_t i=0; i < _countof(g_WICFormats); ++i )
|
||||
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
|
||||
{
|
||||
if ( memcmp( &g_WICFormats[i].wic, &sourceGUID, sizeof(GUID) ) == 0 )
|
||||
if (memcmp(&g_WICFormats[i].wic, &sourceGUID, sizeof(GUID)) == 0)
|
||||
{
|
||||
if ( g_WICFormats[i].srgb )
|
||||
if (g_WICFormats[i].srgb)
|
||||
srgb |= TEX_FILTER_SRGB_IN;
|
||||
}
|
||||
|
||||
if ( memcmp( &g_WICFormats[i].wic, &targetGUID, sizeof(GUID) ) == 0 )
|
||||
if (memcmp(&g_WICFormats[i].wic, &targetGUID, sizeof(GUID)) == 0)
|
||||
{
|
||||
if ( g_WICFormats[i].srgb )
|
||||
if (g_WICFormats[i].srgb)
|
||||
srgb |= TEX_FILTER_SRGB_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (srgb & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
|
||||
if ((srgb & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT))
|
||||
{
|
||||
srgb &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
|
||||
srgb &= ~(TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT);
|
||||
}
|
||||
|
||||
return srgb;
|
||||
@ -195,9 +195,9 @@ DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetG
|
||||
// Public helper function to get common WIC codec GUIDs
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
REFGUID GetWICCodec( WICCodecs codec )
|
||||
REFGUID DirectX::GetWICCodec(WICCodecs codec)
|
||||
{
|
||||
switch( codec )
|
||||
switch (codec)
|
||||
{
|
||||
case WIC_CODEC_BMP:
|
||||
return GUID_ContainerFormatBmp;
|
||||
@ -229,9 +229,9 @@ REFGUID GetWICCodec( WICCodecs codec )
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Singleton function for WIC factory
|
||||
//-------------------------------------------------------------------------------------
|
||||
IWICImagingFactory* GetWICFactory( bool& iswic2 )
|
||||
IWICImagingFactory* DirectX::GetWICFactory(bool& iswic2)
|
||||
{
|
||||
if ( g_Factory )
|
||||
if (g_Factory)
|
||||
{
|
||||
iswic2 = g_WIC2;
|
||||
return g_Factory;
|
||||
@ -240,47 +240,47 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
|
||||
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
InitOnceExecuteOnce(&s_initOnce,
|
||||
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
|
||||
[](PINIT_ONCE, PVOID, LPVOID *factory) -> BOOL
|
||||
{
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
HRESULT hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory2,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory2),
|
||||
factory
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
|
||||
g_WIC2 = true;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
HRESULT hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory2,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory2),
|
||||
factory
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
|
||||
g_WIC2 = true;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_WIC2 = false;
|
||||
|
||||
hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory1,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory),
|
||||
factory
|
||||
);
|
||||
return SUCCEEDED(hr) ? TRUE : FALSE;
|
||||
}
|
||||
#else
|
||||
g_WIC2 = false;
|
||||
|
||||
return SUCCEEDED( CoCreateInstance(
|
||||
CLSID_WICImagingFactory,
|
||||
hr = CoCreateInstance(
|
||||
CLSID_WICImagingFactory1,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory),
|
||||
factory) ) ? TRUE : FALSE;
|
||||
#endif
|
||||
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory) );
|
||||
factory
|
||||
);
|
||||
return SUCCEEDED(hr) ? TRUE : FALSE;
|
||||
}
|
||||
#else
|
||||
g_WIC2 = false;
|
||||
|
||||
return SUCCEEDED(CoCreateInstance(
|
||||
CLSID_WICImagingFactory,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IWICImagingFactory),
|
||||
factory)) ? TRUE : FALSE;
|
||||
#endif
|
||||
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory));
|
||||
|
||||
iswic2 = g_WIC2;
|
||||
return g_Factory;
|
||||
@ -290,7 +290,7 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Optional initializer for WIC factory
|
||||
//-------------------------------------------------------------------------------------
|
||||
void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
||||
void DirectX::SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
||||
{
|
||||
if (pWIC == g_Factory)
|
||||
return;
|
||||
@ -311,7 +311,7 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
||||
|
||||
g_WIC2 = iswic2;
|
||||
std::swap(pWIC, g_Factory);
|
||||
if ( pWIC )
|
||||
if (pWIC)
|
||||
pWIC->Release();
|
||||
}
|
||||
|
||||
@ -323,9 +323,9 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
bool IsPacked(DXGI_FORMAT fmt)
|
||||
bool DirectX::IsPacked(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_R8G8_B8G8_UNORM:
|
||||
case DXGI_FORMAT_G8R8_G8B8_UNORM:
|
||||
@ -342,9 +342,9 @@ bool IsPacked(DXGI_FORMAT fmt)
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
bool IsVideo(DXGI_FORMAT fmt)
|
||||
bool DirectX::IsVideo(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch ( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_AYUV:
|
||||
case DXGI_FORMAT_Y410:
|
||||
@ -379,9 +379,9 @@ bool IsVideo(DXGI_FORMAT fmt)
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
bool IsPlanar(DXGI_FORMAT fmt)
|
||||
bool DirectX::IsPlanar(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch ( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_NV12: // 4:2:0 8-bit
|
||||
case DXGI_FORMAT_P010: // 4:2:0 10-bit
|
||||
@ -403,15 +403,14 @@ bool IsPlanar(DXGI_FORMAT fmt)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
bool IsDepthStencil(DXGI_FORMAT fmt)
|
||||
bool DirectX::IsDepthStencil(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
||||
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
||||
@ -434,9 +433,9 @@ bool IsDepthStencil(DXGI_FORMAT fmt)
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
bool IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
|
||||
bool DirectX::IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
|
||||
{
|
||||
switch( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||
case DXGI_FORMAT_R32G32B32_TYPELESS:
|
||||
@ -478,9 +477,9 @@ bool IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
bool HasAlpha(DXGI_FORMAT fmt)
|
||||
bool DirectX::HasAlpha(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
@ -541,9 +540,9 @@ bool HasAlpha(DXGI_FORMAT fmt)
|
||||
// Returns bits-per-pixel for a given DXGI format, or 0 on failure
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
size_t BitsPerPixel( DXGI_FORMAT fmt )
|
||||
size_t DirectX::BitsPerPixel(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
@ -703,9 +702,9 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
|
||||
// For mixed formats, it returns the largest color-depth in the format
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
size_t BitsPerColor( DXGI_FORMAT fmt )
|
||||
size_t DirectX::BitsPerColor(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
@ -869,10 +868,10 @@ size_t BitsPerColor( DXGI_FORMAT fmt )
|
||||
// based on DXGI format, width, and height
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
size_t& rowPitch, size_t& slicePitch, DWORD flags )
|
||||
void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
size_t& rowPitch, size_t& slicePitch, DWORD flags)
|
||||
{
|
||||
switch( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_BC1_TYPELESS:
|
||||
case DXGI_FORMAT_BC1_UNORM:
|
||||
@ -882,8 +881,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
case DXGI_FORMAT_BC4_SNORM:
|
||||
assert(IsCompressed(fmt));
|
||||
{
|
||||
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
|
||||
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
|
||||
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||
rowPitch = nbw * 8;
|
||||
|
||||
slicePitch = rowPitch * nbh;
|
||||
@ -907,8 +906,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
assert(IsCompressed(fmt));
|
||||
{
|
||||
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
|
||||
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
|
||||
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
|
||||
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
|
||||
rowPitch = nbw * 16;
|
||||
|
||||
slicePitch = rowPitch * nbh;
|
||||
@ -919,22 +918,22 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
case DXGI_FORMAT_G8R8_G8B8_UNORM:
|
||||
case DXGI_FORMAT_YUY2:
|
||||
assert(IsPacked(fmt));
|
||||
rowPitch = ( ( width + 1 ) >> 1 ) * 4;
|
||||
rowPitch = ((width + 1) >> 1) * 4;
|
||||
slicePitch = rowPitch * height;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_Y210:
|
||||
case DXGI_FORMAT_Y216:
|
||||
assert(IsPacked(fmt));
|
||||
rowPitch = ( ( width + 1 ) >> 1 ) * 8;
|
||||
rowPitch = ((width + 1) >> 1) * 8;
|
||||
slicePitch = rowPitch * height;
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_NV12:
|
||||
case DXGI_FORMAT_420_OPAQUE:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ( ( width + 1 ) >> 1 ) * 2;
|
||||
slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
|
||||
rowPitch = ((width + 1) >> 1) * 2;
|
||||
slicePitch = rowPitch * (height + ((height + 1) >> 1));
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_P010:
|
||||
@ -943,84 +942,84 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
|
||||
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ( ( width + 1 ) >> 1 ) * 4;
|
||||
slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
|
||||
rowPitch = ((width + 1) >> 1) * 4;
|
||||
slicePitch = rowPitch * (height + ((height + 1) >> 1));
|
||||
break;
|
||||
|
||||
case DXGI_FORMAT_NV11:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ( ( width + 3 ) >> 2 ) * 4;
|
||||
rowPitch = ((width + 3) >> 2) * 4;
|
||||
slicePitch = rowPitch * height * 2;
|
||||
break;
|
||||
|
||||
case WIN10_DXGI_FORMAT_P208:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = ( ( width + 1 ) >> 1 ) * 2;
|
||||
rowPitch = ((width + 1) >> 1) * 2;
|
||||
slicePitch = rowPitch * height * 2;
|
||||
break;
|
||||
|
||||
case WIN10_DXGI_FORMAT_V208:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = width;
|
||||
slicePitch = rowPitch * ( height + ( ( ( height + 1 ) >> 1 ) * 2 ) );
|
||||
slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2));
|
||||
break;
|
||||
|
||||
case WIN10_DXGI_FORMAT_V408:
|
||||
assert(IsPlanar(fmt));
|
||||
rowPitch = width;
|
||||
slicePitch = rowPitch * ( height + ( ( height >> 1 ) * 4 ) );
|
||||
slicePitch = rowPitch * (height + ((height >> 1) * 4));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( IsValid(fmt) );
|
||||
assert( !IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt) );
|
||||
assert(IsValid(fmt));
|
||||
assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt));
|
||||
{
|
||||
|
||||
size_t bpp;
|
||||
|
||||
if ( flags & CP_FLAGS_24BPP )
|
||||
if (flags & CP_FLAGS_24BPP)
|
||||
bpp = 24;
|
||||
else if ( flags & CP_FLAGS_16BPP )
|
||||
else if (flags & CP_FLAGS_16BPP)
|
||||
bpp = 16;
|
||||
else if ( flags & CP_FLAGS_8BPP )
|
||||
else if (flags & CP_FLAGS_8BPP)
|
||||
bpp = 8;
|
||||
else
|
||||
bpp = BitsPerPixel( fmt );
|
||||
bpp = BitsPerPixel(fmt);
|
||||
|
||||
if ( flags & ( CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K ) )
|
||||
if (flags & (CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K))
|
||||
{
|
||||
if ( flags & CP_FLAGS_PAGE4K )
|
||||
if (flags & CP_FLAGS_PAGE4K)
|
||||
{
|
||||
rowPitch = ( ( width * bpp + 32767 ) / 32768 ) * 4096;
|
||||
rowPitch = ((width * bpp + 32767) / 32768) * 4096;
|
||||
slicePitch = rowPitch * height;
|
||||
}
|
||||
else if ( flags & CP_FLAGS_ZMM )
|
||||
else if (flags & CP_FLAGS_ZMM)
|
||||
{
|
||||
rowPitch = ( ( width * bpp + 511 ) / 512 ) * 64;
|
||||
rowPitch = ((width * bpp + 511) / 512) * 64;
|
||||
slicePitch = rowPitch * height;
|
||||
}
|
||||
else if ( flags & CP_FLAGS_YMM )
|
||||
else if (flags & CP_FLAGS_YMM)
|
||||
{
|
||||
rowPitch = ( ( width * bpp + 255 ) / 256) * 32;
|
||||
rowPitch = ((width * bpp + 255) / 256) * 32;
|
||||
slicePitch = rowPitch * height;
|
||||
}
|
||||
else if ( flags & CP_FLAGS_PARAGRAPH )
|
||||
else if (flags & CP_FLAGS_PARAGRAPH)
|
||||
{
|
||||
rowPitch = ( ( width * bpp + 127 ) / 128 ) * 16;
|
||||
rowPitch = ((width * bpp + 127) / 128) * 16;
|
||||
slicePitch = rowPitch * height;
|
||||
}
|
||||
else // DWORD alignment
|
||||
{
|
||||
// Special computation for some incorrectly created DDS files based on
|
||||
// legacy DirectDraw assumptions about pitch alignment
|
||||
rowPitch = ( ( width * bpp + 31 ) / 32 ) * sizeof(uint32_t);
|
||||
rowPitch = ((width * bpp + 31) / 32) * sizeof(uint32_t);
|
||||
slicePitch = rowPitch * height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default byte alignment
|
||||
rowPitch = ( width * bpp + 7 ) / 8;
|
||||
rowPitch = (width * bpp + 7) / 8;
|
||||
slicePitch = rowPitch * height;
|
||||
}
|
||||
}
|
||||
@ -1031,9 +1030,9 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
||||
size_t DirectX::ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
||||
{
|
||||
switch ( static_cast<int>(fmt) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_BC1_TYPELESS:
|
||||
case DXGI_FORMAT_BC1_UNORM:
|
||||
@ -1057,7 +1056,7 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
||||
case DXGI_FORMAT_BC7_UNORM:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
assert(IsCompressed(fmt));
|
||||
return std::max<size_t>( 1, (height + 3) / 4 );
|
||||
return std::max<size_t>(1, (height + 3) / 4);
|
||||
|
||||
case DXGI_FORMAT_NV11:
|
||||
case WIN10_DXGI_FORMAT_P208:
|
||||
@ -1066,11 +1065,11 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
||||
|
||||
case WIN10_DXGI_FORMAT_V208:
|
||||
assert(IsPlanar(fmt));
|
||||
return height + ( ( (height + 1) >> 1 ) * 2 );
|
||||
return height + (((height + 1) >> 1) * 2);
|
||||
|
||||
case WIN10_DXGI_FORMAT_V408:
|
||||
assert(IsPlanar(fmt));
|
||||
return height + ( (height >> 1) * 4 );
|
||||
return height + ((height >> 1) * 4);
|
||||
|
||||
case DXGI_FORMAT_NV12:
|
||||
case DXGI_FORMAT_P010:
|
||||
@ -1080,11 +1079,11 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
||||
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
|
||||
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
|
||||
assert(IsPlanar(fmt));
|
||||
return height + ( ( height + 1 ) >> 1 );
|
||||
return height + ((height + 1) >> 1);
|
||||
|
||||
default:
|
||||
assert( IsValid(fmt) );
|
||||
assert( !IsCompressed(fmt) && !IsPlanar(fmt) );
|
||||
assert(IsValid(fmt));
|
||||
assert(!IsCompressed(fmt) && !IsPlanar(fmt));
|
||||
return height;
|
||||
}
|
||||
}
|
||||
@ -1094,9 +1093,9 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
|
||||
// Converts to an SRGB equivalent type if available
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
|
||||
DXGI_FORMAT DirectX::MakeSRGB(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( fmt )
|
||||
switch (fmt)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
@ -1129,9 +1128,9 @@ DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
|
||||
// Converts to a format to an equivalent TYPELESS format if available
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
|
||||
DXGI_FORMAT DirectX::MakeTypeless(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( static_cast<int>( fmt ) )
|
||||
switch (static_cast<int>(fmt))
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
case DXGI_FORMAT_R32G32B32A32_UINT:
|
||||
@ -1249,9 +1248,9 @@ DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
|
||||
// Converts to a TYPELESS format to an equivalent UNORM format if available
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
|
||||
DXGI_FORMAT DirectX::MakeTypelessUNORM(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( fmt )
|
||||
switch (fmt)
|
||||
{
|
||||
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
|
||||
return DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
@ -1308,9 +1307,9 @@ DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
|
||||
// Converts to a TYPELESS format to an equivalent FLOAT format if available
|
||||
//-------------------------------------------------------------------------------------
|
||||
_Use_decl_annotations_
|
||||
DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
|
||||
DXGI_FORMAT DirectX::MakeTypelessFLOAT(DXGI_FORMAT fmt)
|
||||
{
|
||||
switch( fmt )
|
||||
switch (fmt)
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
@ -1344,25 +1343,25 @@ DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
|
||||
//=====================================================================================
|
||||
|
||||
_Use_decl_annotations_
|
||||
size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
|
||||
size_t TexMetadata::ComputeIndex(size_t mip, size_t item, size_t slice) const
|
||||
{
|
||||
if ( mip >= mipLevels )
|
||||
if (mip >= mipLevels)
|
||||
return size_t(-1);
|
||||
|
||||
switch( dimension )
|
||||
switch (dimension)
|
||||
{
|
||||
case TEX_DIMENSION_TEXTURE1D:
|
||||
case TEX_DIMENSION_TEXTURE2D:
|
||||
if ( slice > 0 )
|
||||
if (slice > 0)
|
||||
return size_t(-1);
|
||||
|
||||
if ( item >= arraySize )
|
||||
if (item >= arraySize)
|
||||
return size_t(-1);
|
||||
|
||||
return (item*( mipLevels ) + mip);
|
||||
return (item*(mipLevels)+mip);
|
||||
|
||||
case TEX_DIMENSION_TEXTURE3D:
|
||||
if ( item > 0 )
|
||||
if (item > 0)
|
||||
{
|
||||
// No support for arrays of volumes
|
||||
return size_t(-1);
|
||||
@ -1372,14 +1371,14 @@ size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
|
||||
size_t index = 0;
|
||||
size_t d = depth;
|
||||
|
||||
for( size_t level = 0; level < mip; ++level )
|
||||
for (size_t level = 0; level < mip; ++level)
|
||||
{
|
||||
index += d;
|
||||
if ( d > 1 )
|
||||
if (d > 1)
|
||||
d >>= 1;
|
||||
}
|
||||
|
||||
if ( slice >= d )
|
||||
if (slice >= d)
|
||||
return size_t(-1);
|
||||
|
||||
index += slice;
|
||||
@ -1400,48 +1399,46 @@ size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
|
||||
|
||||
Blob& Blob::operator= (Blob&& moveFrom)
|
||||
{
|
||||
if ( this != &moveFrom )
|
||||
if (this != &moveFrom)
|
||||
{
|
||||
Release();
|
||||
|
||||
_buffer = moveFrom._buffer;
|
||||
_size = moveFrom._size;
|
||||
m_buffer = moveFrom.m_buffer;
|
||||
m_size = moveFrom.m_size;
|
||||
|
||||
moveFrom._buffer = nullptr;
|
||||
moveFrom._size = 0;
|
||||
moveFrom.m_buffer = nullptr;
|
||||
moveFrom.m_size = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Blob::Release()
|
||||
{
|
||||
if ( _buffer )
|
||||
if (m_buffer)
|
||||
{
|
||||
_aligned_free( _buffer );
|
||||
_buffer = nullptr;
|
||||
_aligned_free(m_buffer);
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
|
||||
_size = 0;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
HRESULT Blob::Initialize( size_t size )
|
||||
HRESULT Blob::Initialize(size_t size)
|
||||
{
|
||||
if ( !size )
|
||||
if (!size)
|
||||
return E_INVALIDARG;
|
||||
|
||||
Release();
|
||||
|
||||
_buffer = _aligned_malloc( size, 16 );
|
||||
if ( !_buffer )
|
||||
m_buffer = _aligned_malloc(size, 16);
|
||||
if (!m_buffer)
|
||||
{
|
||||
Release();
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_size = size;
|
||||
m_size = size;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -63,36 +63,36 @@ struct LinearFilter
|
||||
float weight1;
|
||||
};
|
||||
|
||||
inline void _CreateLinearFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf )
|
||||
inline void _CreateLinearFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf)
|
||||
{
|
||||
assert( source > 0 );
|
||||
assert( dest > 0 );
|
||||
assert( lf != 0 );
|
||||
assert(source > 0);
|
||||
assert(dest > 0);
|
||||
assert(lf != 0);
|
||||
|
||||
float scale = float(source) / float(dest);
|
||||
|
||||
// Mirror is the same case as clamp for linear
|
||||
|
||||
for( size_t u = 0; u < dest; ++u )
|
||||
for (size_t u = 0; u < dest; ++u)
|
||||
{
|
||||
float srcB = ( float(u) + 0.5f ) * scale + 0.5f;
|
||||
float srcB = (float(u) + 0.5f) * scale + 0.5f;
|
||||
|
||||
ptrdiff_t isrcB = ptrdiff_t(srcB);
|
||||
ptrdiff_t isrcA = isrcB - 1;
|
||||
|
||||
if ( isrcA < 0 )
|
||||
if (isrcA < 0)
|
||||
{
|
||||
isrcA = ( wrap ) ? ( source - 1) : 0;
|
||||
isrcA = (wrap) ? (source - 1) : 0;
|
||||
}
|
||||
|
||||
if ( size_t(isrcB) >= source )
|
||||
if (size_t(isrcB) >= source)
|
||||
{
|
||||
isrcB = ( wrap ) ? 0 : ( source - 1);
|
||||
isrcB = (wrap) ? 0 : (source - 1);
|
||||
}
|
||||
|
||||
float weight = 1.0f + float(isrcB) - srcB;
|
||||
|
||||
auto& entry = lf[ u ];
|
||||
auto& entry = lf[u];
|
||||
entry.u0 = size_t(isrcA);
|
||||
entry.weight0 = weight;
|
||||
|
||||
@ -120,34 +120,34 @@ XMGLOBALCONST XMVECTORF32 g_cubicThird = { 1.f/3.f, 1.f/3.f, 1.f/3.f, 1.f/3.f };
|
||||
XMGLOBALCONST XMVECTORF32 g_cubicSixth = { 1.f/6.f, 1.f/6.f, 1.f/6.f, 1.f/6.f };
|
||||
XMGLOBALCONST XMVECTORF32 g_cubicHalf = { 1.f/2.f, 1.f/2.f, 1.f/2.f, 1.f/2.f };
|
||||
|
||||
inline ptrdiff_t bounduvw( ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror )
|
||||
inline ptrdiff_t bounduvw(ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror)
|
||||
{
|
||||
if ( wrap )
|
||||
if (wrap)
|
||||
{
|
||||
if ( u < 0 )
|
||||
if (u < 0)
|
||||
{
|
||||
u = maxu + u + 1;
|
||||
}
|
||||
else if ( u > maxu )
|
||||
else if (u > maxu)
|
||||
{
|
||||
u = u - maxu - 1;
|
||||
}
|
||||
}
|
||||
else if ( mirror )
|
||||
else if (mirror)
|
||||
{
|
||||
if ( u < 0 )
|
||||
if (u < 0)
|
||||
{
|
||||
u = ( -u ) - 1;
|
||||
u = (-u) - 1;
|
||||
}
|
||||
else if ( u > maxu )
|
||||
else if (u > maxu)
|
||||
{
|
||||
u = maxu - (u - maxu - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Handles clamp, but also a safety factor for degenerate images for wrap/mirror
|
||||
u = std::min<ptrdiff_t>( u, maxu );
|
||||
u = std::max<ptrdiff_t>( u, 0 );
|
||||
u = std::min<ptrdiff_t>(u, maxu);
|
||||
u = std::max<ptrdiff_t>(u, 0);
|
||||
|
||||
return u;
|
||||
}
|
||||
@ -161,24 +161,24 @@ struct CubicFilter
|
||||
float x;
|
||||
};
|
||||
|
||||
inline void _CreateCubicFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf )
|
||||
inline void _CreateCubicFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf)
|
||||
{
|
||||
assert( source > 0 );
|
||||
assert( dest > 0 );
|
||||
assert( cf != 0 );
|
||||
assert(source > 0);
|
||||
assert(dest > 0);
|
||||
assert(cf != 0);
|
||||
|
||||
float scale = float(source) / float(dest);
|
||||
|
||||
for( size_t u = 0; u < dest; ++u )
|
||||
for (size_t u = 0; u < dest; ++u)
|
||||
{
|
||||
float srcB = ( float(u) + 0.5f ) * scale - 0.5f;
|
||||
float srcB = (float(u) + 0.5f) * scale - 0.5f;
|
||||
|
||||
ptrdiff_t isrcB = bounduvw( ptrdiff_t(srcB), source - 1, wrap, mirror );
|
||||
ptrdiff_t isrcA = bounduvw( isrcB - 1, source - 1, wrap, mirror );
|
||||
ptrdiff_t isrcC = bounduvw( isrcB + 1, source - 1, wrap, mirror );
|
||||
ptrdiff_t isrcD = bounduvw( isrcB + 2, source - 1, wrap, mirror );
|
||||
ptrdiff_t isrcB = bounduvw(ptrdiff_t(srcB), source - 1, wrap, mirror);
|
||||
ptrdiff_t isrcA = bounduvw(isrcB - 1, source - 1, wrap, mirror);
|
||||
ptrdiff_t isrcC = bounduvw(isrcB + 1, source - 1, wrap, mirror);
|
||||
ptrdiff_t isrcD = bounduvw(isrcB + 2, source - 1, wrap, mirror);
|
||||
|
||||
auto& entry = cf[ u ];
|
||||
auto& entry = cf[u];
|
||||
entry.u0 = size_t(isrcA);
|
||||
entry.u1 = size_t(isrcB);
|
||||
entry.u2 = size_t(isrcC);
|
||||
@ -246,10 +246,10 @@ namespace TriangleFilter
|
||||
|
||||
static const float TF_EPSILON = 0.00001f;
|
||||
|
||||
inline HRESULT _Create( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf )
|
||||
inline HRESULT _Create(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf)
|
||||
{
|
||||
assert( source > 0 );
|
||||
assert( dest > 0 );
|
||||
assert(source > 0);
|
||||
assert(dest > 0);
|
||||
|
||||
float scale = float(dest) / float(source);
|
||||
float scaleInv = 0.5f / scale;
|
||||
@ -258,109 +258,109 @@ namespace TriangleFilter
|
||||
size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE;
|
||||
float repeat = (wrap) ? 1.f : 0.f;
|
||||
|
||||
for( size_t u = 0; u < source; ++u )
|
||||
for (size_t u = 0; u < source; ++u)
|
||||
{
|
||||
float src = float(u) - 0.5f;
|
||||
float destMin = src * scale;
|
||||
float destMax = destMin + scale;
|
||||
|
||||
totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t( destMax - destMin + repeat + 1.f ) * TF_TO_SIZE * 2;
|
||||
totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t(destMax - destMin + repeat + 1.f) * TF_TO_SIZE * 2;
|
||||
}
|
||||
|
||||
uint8_t* pFilter = nullptr;
|
||||
|
||||
if ( tf )
|
||||
if (tf)
|
||||
{
|
||||
// See if existing filter memory block is large enough to reuse
|
||||
if ( tf->totalSize >= totalSize )
|
||||
if (tf->totalSize >= totalSize)
|
||||
{
|
||||
pFilter = reinterpret_cast<uint8_t*>( tf.get() );
|
||||
pFilter = reinterpret_cast<uint8_t*>(tf.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to reallocate filter memory block
|
||||
tf.reset( nullptr );
|
||||
tf.reset(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !tf )
|
||||
if (!tf)
|
||||
{
|
||||
// Allocate filter memory block
|
||||
pFilter = new (std::nothrow) uint8_t[ totalSize ];
|
||||
if ( !pFilter )
|
||||
pFilter = new (std::nothrow) uint8_t[totalSize];
|
||||
if (!pFilter)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
tf.reset( reinterpret_cast<Filter*>( pFilter ) );
|
||||
tf.reset(reinterpret_cast<Filter*>(pFilter));
|
||||
tf->totalSize = totalSize;
|
||||
}
|
||||
|
||||
assert( pFilter != 0 );
|
||||
assert(pFilter != 0);
|
||||
|
||||
// Filter setup
|
||||
size_t sizeInBytes = TF_FILTER_SIZE;
|
||||
size_t accumU = 0;
|
||||
float accumWeight = 0.f;
|
||||
|
||||
for( size_t u = 0; u < source; ++u )
|
||||
for (size_t u = 0; u < source; ++u)
|
||||
{
|
||||
// Setup from entry
|
||||
size_t sizeFrom = sizeInBytes;
|
||||
auto pFrom = reinterpret_cast<FilterFrom*>( pFilter + sizeInBytes );
|
||||
auto pFrom = reinterpret_cast<FilterFrom*>(pFilter + sizeInBytes);
|
||||
sizeInBytes += TF_FROM_SIZE;
|
||||
|
||||
if ( sizeInBytes > totalSize )
|
||||
if (sizeInBytes > totalSize)
|
||||
return E_FAIL;
|
||||
|
||||
size_t toCount = 0;
|
||||
|
||||
// Perform two passes to capture the influences from both sides
|
||||
for( size_t j = 0; j < 2; ++j )
|
||||
for (size_t j = 0; j < 2; ++j)
|
||||
{
|
||||
float src = float( u + j ) - 0.5f;
|
||||
float src = float(u + j) - 0.5f;
|
||||
|
||||
float destMin = src * scale;
|
||||
float destMax = destMin + scale;
|
||||
|
||||
if ( !wrap )
|
||||
if (!wrap)
|
||||
{
|
||||
// Clamp
|
||||
if ( destMin < 0.f )
|
||||
if (destMin < 0.f)
|
||||
destMin = 0.f;
|
||||
if ( destMax > float(dest) )
|
||||
if (destMax > float(dest))
|
||||
destMax = float(dest);
|
||||
}
|
||||
|
||||
for( auto k = static_cast<ptrdiff_t>( floorf( destMin ) ); float(k) < destMax; ++k )
|
||||
for (auto k = static_cast<ptrdiff_t>(floorf(destMin)); float(k) < destMax; ++k)
|
||||
{
|
||||
float d0 = float(k);
|
||||
float d1 = d0 + 1.f;
|
||||
|
||||
size_t u0;
|
||||
if ( k < 0 )
|
||||
if (k < 0)
|
||||
{
|
||||
// Handle wrap
|
||||
u0 = size_t( k + ptrdiff_t(dest) );
|
||||
u0 = size_t(k + ptrdiff_t(dest));
|
||||
}
|
||||
else if ( k >= ptrdiff_t(dest) )
|
||||
else if (k >= ptrdiff_t(dest))
|
||||
{
|
||||
// Handle wrap
|
||||
u0 = size_t( k - ptrdiff_t(dest) );
|
||||
u0 = size_t(k - ptrdiff_t(dest));
|
||||
}
|
||||
else
|
||||
{
|
||||
u0 = size_t( k );
|
||||
u0 = size_t(k);
|
||||
}
|
||||
|
||||
// Save previous accumulated weight (if any)
|
||||
if ( u0 != accumU )
|
||||
if (u0 != accumU)
|
||||
{
|
||||
if ( accumWeight > TF_EPSILON )
|
||||
if (accumWeight > TF_EPSILON)
|
||||
{
|
||||
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
|
||||
auto pTo = reinterpret_cast<FilterTo*>(pFilter + sizeInBytes);
|
||||
sizeInBytes += TF_TO_SIZE;
|
||||
++toCount;
|
||||
|
||||
if ( sizeInBytes > totalSize )
|
||||
if (sizeInBytes > totalSize)
|
||||
return E_FAIL;
|
||||
|
||||
pTo->u = accumU;
|
||||
@ -372,33 +372,33 @@ namespace TriangleFilter
|
||||
}
|
||||
|
||||
// Clip destination
|
||||
if ( d0 < destMin )
|
||||
if (d0 < destMin)
|
||||
d0 = destMin;
|
||||
if ( d1 > destMax )
|
||||
if (d1 > destMax)
|
||||
d1 = destMax;
|
||||
|
||||
// Calculate average weight over destination pixel
|
||||
|
||||
float weight;
|
||||
if ( !wrap && src < 0.f )
|
||||
if (!wrap && src < 0.f)
|
||||
weight = 1.f;
|
||||
else if ( !wrap && ( ( src + 1.f ) >= float(source) ) )
|
||||
else if (!wrap && ((src + 1.f) >= float(source)))
|
||||
weight = 0.f;
|
||||
else
|
||||
weight = (d0 + d1) * scaleInv - src;
|
||||
|
||||
accumWeight += (d1 - d0) * ( j ? (1.f - weight) : weight );
|
||||
accumWeight += (d1 - d0) * (j ? (1.f - weight) : weight);
|
||||
}
|
||||
}
|
||||
|
||||
// Store accumulated weight
|
||||
if ( accumWeight > TF_EPSILON )
|
||||
if (accumWeight > TF_EPSILON)
|
||||
{
|
||||
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
|
||||
auto pTo = reinterpret_cast<FilterTo*>(pFilter + sizeInBytes);
|
||||
sizeInBytes += TF_TO_SIZE;
|
||||
++toCount;
|
||||
|
||||
if ( sizeInBytes > totalSize )
|
||||
if (sizeInBytes > totalSize)
|
||||
return E_FAIL;
|
||||
|
||||
pTo->u = accumU;
|
||||
@ -417,6 +417,6 @@ namespace TriangleFilter
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
}; // namespace TriangleFilter
|
||||
|
||||
}; // namespace
|
||||
}; // namespace DirectX
|
@ -229,7 +229,7 @@ namespace
|
||||
class auto_delete_file_wic
|
||||
{
|
||||
public:
|
||||
auto_delete_file_wic(ComPtr<IWICStream>& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {}
|
||||
auto_delete_file_wic(ComPtr<IWICStream>& hFile, const wchar_t* szFile) : m_handle(hFile), m_filename(szFile) {}
|
||||
~auto_delete_file_wic()
|
||||
{
|
||||
if (m_filename)
|
||||
@ -242,7 +242,7 @@ namespace
|
||||
void clear() { m_filename = 0; }
|
||||
|
||||
private:
|
||||
LPCWSTR m_filename;
|
||||
const wchar_t* m_filename;
|
||||
ComPtr<IWICStream>& m_handle;
|
||||
|
||||
auto_delete_file_wic(const auto_delete_file_wic&) = delete;
|
||||
@ -705,7 +705,7 @@ namespace
|
||||
|
||||
IWICImagingFactory* factory = nullptr;
|
||||
InitOnceExecuteOnce(&s_initOnce,
|
||||
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
|
||||
[](PINIT_ONCE, PVOID, LPVOID *factory) -> BOOL
|
||||
{
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
|
||||
HRESULT hr = CoCreateInstance(
|
||||
@ -751,7 +751,7 @@ namespace
|
||||
//--------------------------------------------------------------------------------------
|
||||
HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
_In_ ID3D11Resource* pSource,
|
||||
_In_z_ LPCWSTR fileName )
|
||||
_In_z_ const wchar_t* fileName )
|
||||
{
|
||||
if ( !fileName )
|
||||
return E_INVALIDARG;
|
||||
@ -764,9 +764,9 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
|
||||
// Create file
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
||||
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, 0 ) ) );
|
||||
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr ) ) );
|
||||
#else
|
||||
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE | DELETE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
|
||||
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, nullptr ) ) );
|
||||
#endif
|
||||
if ( !hFile )
|
||||
return HRESULT_FROM_WIN32( GetLastError() );
|
||||
@ -912,7 +912,7 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
_In_ ID3D11Resource* pSource,
|
||||
_In_ REFGUID guidContainerFormat,
|
||||
_In_z_ LPCWSTR fileName,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_In_opt_ const GUID* targetFormat,
|
||||
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps )
|
||||
{
|
||||
|
@ -32,12 +32,12 @@ namespace DirectX
|
||||
{
|
||||
HRESULT SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
_In_ ID3D11Resource* pSource,
|
||||
_In_z_ LPCWSTR fileName );
|
||||
_In_z_ const wchar_t* fileName );
|
||||
|
||||
HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
|
||||
_In_ ID3D11Resource* pSource,
|
||||
_In_ REFGUID guidContainerFormat,
|
||||
_In_z_ LPCWSTR fileName,
|
||||
_In_z_ const wchar_t* fileName,
|
||||
_In_opt_ const GUID* targetFormat = nullptr,
|
||||
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps = nullptr );
|
||||
}
|
@ -839,11 +839,7 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
|
||||
return hr;
|
||||
|
||||
// Create file
|
||||
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
|
||||
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0 ) ) );
|
||||
#else
|
||||
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
|
||||
#endif
|
||||
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, nullptr ) ) );
|
||||
if ( !hFile )
|
||||
return HRESULT_FROM_WIN32( GetLastError() );
|
||||
|
||||
@ -972,13 +968,13 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
|
||||
|
||||
// Write header & pixels
|
||||
DWORD bytesWritten;
|
||||
if ( !WriteFile( hFile.get(), fileHeader, static_cast<DWORD>( headerSize ), &bytesWritten, 0 ) )
|
||||
if ( !WriteFile( hFile.get(), fileHeader, static_cast<DWORD>( headerSize ), &bytesWritten, nullptr ) )
|
||||
return HRESULT_FROM_WIN32( GetLastError() );
|
||||
|
||||
if ( bytesWritten != headerSize )
|
||||
return E_FAIL;
|
||||
|
||||
if ( !WriteFile( hFile.get(), pixels.get(), static_cast<DWORD>( slicePitch ), &bytesWritten, 0 ) )
|
||||
if ( !WriteFile( hFile.get(), pixels.get(), static_cast<DWORD>( slicePitch ), &bytesWritten, nullptr ) )
|
||||
return HRESULT_FROM_WIN32( GetLastError() );
|
||||
|
||||
if ( bytesWritten != slicePitch )
|
||||
|
@ -34,90 +34,98 @@
|
||||
namespace DirectX
|
||||
{
|
||||
// Standard version
|
||||
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
HRESULT CreateWICTextureFromMemory(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
|
||||
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
HRESULT CreateWICTextureFromFile(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
|
||||
// Standard version with optional auto-gen mipmap support
|
||||
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
HRESULT CreateWICTextureFromMemory(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
|
||||
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
HRESULT CreateWICTextureFromFile(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView,
|
||||
_In_ size_t maxsize = 0
|
||||
);
|
||||
|
||||
// Extended version
|
||||
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
HRESULT CreateWICTextureFromMemoryEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_In_ size_t maxsize,
|
||||
D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
|
||||
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
HRESULT CreateWICTextureFromFileEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
|
||||
// Extended version with optional auto-gen mipmap support
|
||||
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
HRESULT CreateWICTextureFromMemoryEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
|
||||
_In_ size_t wicDataSize,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
|
||||
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
HRESULT CreateWICTextureFromFileEx(
|
||||
_In_ ID3D11Device* d3dDevice,
|
||||
_In_opt_ ID3D11DeviceContext* d3dContext,
|
||||
_In_z_ const wchar_t* szFileName,
|
||||
_In_ size_t maxsize,
|
||||
_In_ D3D11_USAGE usage,
|
||||
_In_ unsigned int bindFlags,
|
||||
_In_ unsigned int cpuAccessFlags,
|
||||
_In_ unsigned int miscFlags,
|
||||
_In_ bool forceSRGB,
|
||||
_Out_opt_ ID3D11Resource** texture,
|
||||
_Out_opt_ ID3D11ShaderResourceView** textureView
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user