|
|
|
@ -83,51 +83,7 @@ void CDXTCImage::Clear()
|
|
|
|
|
Initialize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CDXTCImage::LoadFromFile(const char * filename)
|
|
|
|
|
{
|
|
|
|
|
// only understands .dds files for now
|
|
|
|
|
// return true if success
|
|
|
|
|
char * exts[] = { ".DDS" };
|
|
|
|
|
int next = 1;
|
|
|
|
|
|
|
|
|
|
static char fileupper[MAX_PATH+1];
|
|
|
|
|
|
|
|
|
|
strncpy(fileupper, filename, MAX_PATH);
|
|
|
|
|
strupr(fileupper);
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
bool knownformat = false;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < next; ++i)
|
|
|
|
|
{
|
|
|
|
|
char * found = strstr(fileupper, exts[0]);
|
|
|
|
|
|
|
|
|
|
if (found != NULL)
|
|
|
|
|
{
|
|
|
|
|
knownformat = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (knownformat == false)
|
|
|
|
|
{
|
|
|
|
|
Tracef("Unknown file format encountered! [%s]\n", filename);
|
|
|
|
|
return(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CMappedFile mappedFile;
|
|
|
|
|
LPCVOID pvMap;
|
|
|
|
|
|
|
|
|
|
if (!mappedFile.Create(filename, &pvMap, 0, 0))
|
|
|
|
|
{
|
|
|
|
|
Tracef("Can't open file for reading! [%s]\n", filename);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LoadFromMemory((const BYTE*) pvMap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap)
|
|
|
|
|
bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap, int iSize)
|
|
|
|
|
{
|
|
|
|
|
//////////////////////////////////////
|
|
|
|
|
// start reading the file
|
|
|
|
@ -135,18 +91,26 @@ bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap)
|
|
|
|
|
DWORD dwMagic;
|
|
|
|
|
|
|
|
|
|
// Read magic number
|
|
|
|
|
if (iSize < sizeof(DWORD))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
dwMagic = *(DWORD *) c_pbMap;
|
|
|
|
|
c_pbMap += sizeof(DWORD);
|
|
|
|
|
iSize -= sizeof(DWORD);
|
|
|
|
|
|
|
|
|
|
//!@#
|
|
|
|
|
// if (dwMagic != MAKEFOURCC('D','D','S',' '))
|
|
|
|
|
// return false;
|
|
|
|
|
// Check whether the magic header is correct
|
|
|
|
|
if (dwMagic != MAKEFOURCC('D','D','S',' '))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
DDSURFACEDESC2 ddsd; // read from dds file
|
|
|
|
|
|
|
|
|
|
// Read the surface description
|
|
|
|
|
if (iSize < sizeof(DDSURFACEDESC2))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
memcpy(&ddsd, c_pbMap, sizeof(DDSURFACEDESC2));
|
|
|
|
|
c_pbMap += sizeof(DDSURFACEDESC2);
|
|
|
|
|
iSize -= sizeof(DDSURFACEDESC2);
|
|
|
|
|
|
|
|
|
|
// Does texture have mipmaps?
|
|
|
|
|
m_bMipTexture = (ddsd.dwMipMapCount > 0) ? TRUE : FALSE;
|
|
|
|
@ -211,52 +175,6 @@ bool CDXTCImage::LoadHeaderFromMemory(const BYTE * c_pbMap)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
bool CDXTCImage::LoadFromMemory(const BYTE * c_pbMap)
|
|
|
|
|
{
|
|
|
|
|
if (!LoadHeaderFromMemory(c_pbMap))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (m_dwFlags & DDSD_PITCH)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwBytesPerRow = m_nWidth * m_xddPixelFormat.dwRGBBitCount / 8;
|
|
|
|
|
|
|
|
|
|
m_nCompSize = m_lPitch * m_nHeight;
|
|
|
|
|
m_nCompLineSz = dwBytesPerRow;
|
|
|
|
|
|
|
|
|
|
m_bCompVector[0].resize(m_nCompSize);
|
|
|
|
|
BYTE * pDest = &m_bCompVector[0][0];
|
|
|
|
|
|
|
|
|
|
c_pbMap = m_pbCompBufferByLevels[0];
|
|
|
|
|
|
|
|
|
|
for (int yp = 0; yp < m_nHeight; ++yp)
|
|
|
|
|
{
|
|
|
|
|
memcpy(pDest, c_pbMap, dwBytesPerRow);
|
|
|
|
|
pDest += m_lPitch;
|
|
|
|
|
c_pbMap += m_lPitch;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (m_dwFlags & DDSD_MIPMAPCOUNT)
|
|
|
|
|
{
|
|
|
|
|
for (DWORD dwLinearSize = m_lPitch, i = 0; i < m_dwMipMapCount; ++i, dwLinearSize >>= 2)
|
|
|
|
|
{
|
|
|
|
|
m_bCompVector[i].resize(dwLinearSize);
|
|
|
|
|
Copy(i, &m_bCompVector[i][0], dwLinearSize);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_bCompVector[0].resize(m_lPitch);
|
|
|
|
|
Copy(0, &m_bCompVector[0][0], m_lPitch);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// done reading file
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CDXTCImage::Copy(int miplevel, BYTE * pbDest, long lDestPitch)
|
|
|
|
|
{
|
|
|
|
|
if (!(m_dwFlags & DDSD_MIPMAPCOUNT))
|
|
|
|
@ -959,688 +877,3 @@ VOID CDXTCImage::DecodePixelFormat(CHAR* strPixelFormat, XDDPIXELFORMAT* pxddpf)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
// Struct to hold various timing values
|
|
|
|
|
struct TimingInfo
|
|
|
|
|
{
|
|
|
|
|
LARGE_INTEGER m_start_clk;
|
|
|
|
|
LARGE_INTEGER m_end_clk;
|
|
|
|
|
|
|
|
|
|
int m_nSamples;
|
|
|
|
|
LARGE_INTEGER m_interval_sum; // sum of all end-start, nSamples number added in
|
|
|
|
|
|
|
|
|
|
CString m_csName; // text desc of what timed
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void CDXTCImage::RunTimingSession()
|
|
|
|
|
{
|
|
|
|
|
// Must have a dxt5 texture loaded
|
|
|
|
|
// No special reason - just lazy coding
|
|
|
|
|
// Functions called to time code are separate from non-timed
|
|
|
|
|
// code. It's alogorithm that counts.
|
|
|
|
|
ASSERT(m_pCompBytes != NULL);
|
|
|
|
|
ASSERT(m_pDecompBytes != NULL); // must already have allocated memory
|
|
|
|
|
|
|
|
|
|
switch (m_CompFormat)
|
|
|
|
|
{
|
|
|
|
|
case PF_DXT1:
|
|
|
|
|
case PF_DXT2:
|
|
|
|
|
case PF_DXT3:
|
|
|
|
|
case PF_DXT4:
|
|
|
|
|
case PF_UNKNOWN:
|
|
|
|
|
Tracef("You must have a DXT5 texture loaded to RunTimingSession()!!\n");
|
|
|
|
|
Tracef("Now I will be nasty and ASSERT(false)!\n");
|
|
|
|
|
ASSERT(false);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PF_DXT5:
|
|
|
|
|
Tracef("Running code timing session on DXT5 color decompress\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LARGE_INTEGER start_clk, end_clk;
|
|
|
|
|
QueryPerformanceCounter(&start_clk);
|
|
|
|
|
#define NMETHOD 4
|
|
|
|
|
#define NBATCHES 4
|
|
|
|
|
int passes[NBATCHES];
|
|
|
|
|
passes[0] = 1;
|
|
|
|
|
passes[1] = 10;
|
|
|
|
|
passes[2] = 30;
|
|
|
|
|
passes[3] = 50;
|
|
|
|
|
|
|
|
|
|
TimingInfo method[NMETHOD][NBATCHES];
|
|
|
|
|
|
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
|
|
FILE * pf = fopen("timing.txt", "wt");
|
|
|
|
|
|
|
|
|
|
if (pf == NULL)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(pf, "\n\n");
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < NBATCHES; ++i)
|
|
|
|
|
{
|
|
|
|
|
Sleep(50);
|
|
|
|
|
fprintf(pf,"i: %d passes[i]: %d\n", i, passes[i]);
|
|
|
|
|
Time_Decomp5_01(passes[i], &(method[0][i]));
|
|
|
|
|
Time_Decomp5_02(passes[i], &(method[1][i]));
|
|
|
|
|
Time_Decomp5_03(passes[i], &(method[2][i]));
|
|
|
|
|
Time_Decomp5_04(passes[i], &(method[3][i]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QueryPerformanceCounter(&end_clk);
|
|
|
|
|
|
|
|
|
|
// unsigned long total;
|
|
|
|
|
// total = (unsigned long) (end_clk - start_clk);
|
|
|
|
|
LARGE_INTEGER freq;
|
|
|
|
|
QueryPerformanceFrequency(& freq);
|
|
|
|
|
|
|
|
|
|
fprintf(pf, "\nCounter freq = %u %d \n", freq.LowPart, freq.HighPart);
|
|
|
|
|
fprintf(pf, "start: %u %u end: %u %u\n", start_clk.LowPart, start_clk.HighPart, end_clk.LowPart, end_clk.HighPart);
|
|
|
|
|
|
|
|
|
|
Tracef("\nCounter freq = %u %d \n", freq.LowPart, freq.HighPart);
|
|
|
|
|
Tracef("start: %u %u end: %u %u\n", start_clk.LowPart, start_clk.HighPart, end_clk.LowPart, end_clk.HighPart);
|
|
|
|
|
|
|
|
|
|
double dur = ((double)end_clk.LowPart - (double)start_clk.LowPart) / (double)freq.LowPart;
|
|
|
|
|
|
|
|
|
|
fprintf(pf, "Total timing session took: %u cycles = %f seconds\n", (end_clk.LowPart - start_clk.LowPart), dur);
|
|
|
|
|
fprintf(pf, "\n\n");
|
|
|
|
|
|
|
|
|
|
Tracef("Total timing session took: %u cycles = %f seconds\n", (end_clk.LowPart - start_clk.LowPart), dur);
|
|
|
|
|
Tracef("\n\n");
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < NMETHOD; ++n)
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < NBATCHES; ++i)
|
|
|
|
|
{
|
|
|
|
|
fprintf(pf, "method %d:\n", n);
|
|
|
|
|
fprintf(pf, " %s", method[n][i].m_csName);
|
|
|
|
|
fprintf(pf, " tot: %u %u\n", method[n][i].m_interval_sum.HighPart, method[n][i].m_interval_sum.LowPart);
|
|
|
|
|
|
|
|
|
|
Tracef("method %d:\n", n);
|
|
|
|
|
Tracef(" %s", method[n][i].m_csName);
|
|
|
|
|
Tracef(" tot: %u %u\n", method[n][i].m_interval_sum.HighPart, method[n][i].m_interval_sum.LowPart);
|
|
|
|
|
|
|
|
|
|
dur = ((double)method[n][i].m_interval_sum.LowPart) / ((double)method[n][i].m_nSamples * (double)freq.LowPart);
|
|
|
|
|
|
|
|
|
|
fprintf(pf, " avg: %u\n", method[n][i].m_interval_sum.LowPart / method[n][i].m_nSamples);
|
|
|
|
|
fprintf(pf, " avg time: %f sec\n", dur);
|
|
|
|
|
|
|
|
|
|
Tracef(" avg: %u\n", method[n][i].m_interval_sum.LowPart / method[n][i].m_nSamples);
|
|
|
|
|
Tracef(" avg time: %f sec\n", dur);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(pf, "\n\n");
|
|
|
|
|
Tracef("\n\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(pf);
|
|
|
|
|
|
|
|
|
|
MessageBeep(MB_OK);
|
|
|
|
|
//BOOL QueryPerformanceFrequency(
|
|
|
|
|
// LARGE_INTEGER *lpFrequency // address of current frequency
|
|
|
|
|
//);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void GetColorBlockColors_m2(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
|
|
|
|
Color8888 * col_2, Color8888 * col_3,
|
|
|
|
|
WORD & wrd )
|
|
|
|
|
{
|
|
|
|
|
// method 2
|
|
|
|
|
// freak variable bit structure method
|
|
|
|
|
// normal math
|
|
|
|
|
Color565 * pCol;
|
|
|
|
|
|
|
|
|
|
pCol = (Color565*) & (pBlock->col0);
|
|
|
|
|
|
|
|
|
|
col_0->a = 0xff;
|
|
|
|
|
col_0->r = pCol->nRed;
|
|
|
|
|
col_0->r <<= 3; // shift to full precision
|
|
|
|
|
col_0->g = pCol->nGreen;
|
|
|
|
|
col_0->g <<= 2;
|
|
|
|
|
col_0->b = pCol->nBlue;
|
|
|
|
|
col_0->b <<= 3;
|
|
|
|
|
|
|
|
|
|
pCol = (Color565*) & (pBlock->col1);
|
|
|
|
|
col_1->a = 0xff;
|
|
|
|
|
col_1->r = pCol->nRed;
|
|
|
|
|
col_1->r <<= 3; // shift to full precision
|
|
|
|
|
col_1->g = pCol->nGreen;
|
|
|
|
|
col_1->g <<= 2;
|
|
|
|
|
col_1->b = pCol->nBlue;
|
|
|
|
|
col_1->b <<= 3;
|
|
|
|
|
|
|
|
|
|
if (pBlock->col0 > pBlock->col1)
|
|
|
|
|
{
|
|
|
|
|
// Four-color block: derive the other two colors.
|
|
|
|
|
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
|
|
|
|
|
// These two bit codes correspond to the 2-bit fields
|
|
|
|
|
// stored in the 64-bit block.
|
|
|
|
|
wrd = ((WORD) col_0->r * 2 + (WORD) col_1->r) / 3;
|
|
|
|
|
// no +1 for rounding
|
|
|
|
|
// as bits have been shifted to 888
|
|
|
|
|
col_2->r = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->g * 2 + (WORD) col_1->g) / 3;
|
|
|
|
|
col_2->g = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->b * 2 + (WORD) col_1->b) / 3;
|
|
|
|
|
col_2->b = (BYTE)wrd;
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->r + (WORD) col_1->r * 2) / 3;
|
|
|
|
|
col_3->r = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->g + (WORD) col_1->g * 2) / 3;
|
|
|
|
|
col_3->g = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->b + (WORD) col_1->b * 2) / 3;
|
|
|
|
|
col_3->b = (BYTE)wrd;
|
|
|
|
|
col_3->a = 0xff;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Three-color block: derive the other color.
|
|
|
|
|
// 00 = color_0, 01 = color_1, 10 = color_2,
|
|
|
|
|
// 11 = transparent.
|
|
|
|
|
// These two bit codes correspond to the 2-bit fields
|
|
|
|
|
// stored in the 64-bit block.
|
|
|
|
|
|
|
|
|
|
// explicit for each component, unlike some refrasts...
|
|
|
|
|
|
|
|
|
|
// Tracef("block has alpha\n");
|
|
|
|
|
wrd = ((WORD) col_0->r + (WORD) col_1->r) / 2;
|
|
|
|
|
col_2->r = (BYTE)wrd;
|
|
|
|
|
wrd = ((WORD) col_0->g + (WORD) col_1->g) / 2;
|
|
|
|
|
col_2->g = (BYTE)wrd;
|
|
|
|
|
wrd = ((WORD) col_0->b + (WORD) col_1->b) / 2;
|
|
|
|
|
col_2->b = (BYTE)wrd;
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
|
|
|
|
|
col_3->r = 0x00; // random color to indicate alpha
|
|
|
|
|
col_3->g = 0xff;
|
|
|
|
|
col_3->b = 0xff;
|
|
|
|
|
col_3->a = 0x00;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void GetColorBlockColors_m3(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
|
|
|
|
Color8888 * col_2, Color8888 * col_3,
|
|
|
|
|
WORD & wrd )
|
|
|
|
|
{
|
|
|
|
|
// method 3
|
|
|
|
|
//////////////////////////////////////////////////////
|
|
|
|
|
// super-freak variable bit structure with
|
|
|
|
|
// Cool Math Trick (tm)
|
|
|
|
|
|
|
|
|
|
// Do 2/3 1/3 math BEFORE bit shift on the whole DWORD
|
|
|
|
|
// as the fields will NEVER carry into the next
|
|
|
|
|
// or overflow!! =)
|
|
|
|
|
|
|
|
|
|
Color565 * pCol;
|
|
|
|
|
|
|
|
|
|
pCol = (Color565*) & (pBlock->col0);
|
|
|
|
|
|
|
|
|
|
col_0->a = 0x00; // must set to 0 to avoid overflow in DWORD add
|
|
|
|
|
col_0->r = pCol->nRed;
|
|
|
|
|
col_0->g = pCol->nGreen;
|
|
|
|
|
col_0->b = pCol->nBlue;
|
|
|
|
|
|
|
|
|
|
pCol = (Color565*) & (pBlock->col1);
|
|
|
|
|
col_1->a = 0x00;
|
|
|
|
|
col_1->r = pCol->nRed;
|
|
|
|
|
col_1->g = pCol->nGreen;
|
|
|
|
|
col_1->b = pCol->nBlue;
|
|
|
|
|
|
|
|
|
|
if (pBlock->col0 > pBlock->col1)
|
|
|
|
|
{
|
|
|
|
|
*((DWORD*)col_2) = ((*((DWORD*)col_0)) * 2 + (*((DWORD*)col_1)));
|
|
|
|
|
|
|
|
|
|
*((DWORD*)col_3) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)) * 2);
|
|
|
|
|
|
|
|
|
|
// now shift to appropriate precision & divide by 3.
|
|
|
|
|
col_2->r = ((WORD) col_2->r << 3) / (WORD)3;
|
|
|
|
|
col_2->g = ((WORD) col_2->g << 2) / (WORD)3;
|
|
|
|
|
col_2->b = ((WORD) col_2->b << 3) / (WORD)3;
|
|
|
|
|
|
|
|
|
|
col_3->r = ((WORD) col_3->r << 3) / (WORD)3;
|
|
|
|
|
col_3->g = ((WORD) col_3->g << 2) / (WORD)3;
|
|
|
|
|
col_3->b = ((WORD) col_3->b << 3) / (WORD)3;
|
|
|
|
|
|
|
|
|
|
col_0->a = 0xff; // now set appropriate alpha
|
|
|
|
|
col_1->a = 0xff;
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
col_3->a = 0xff;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*((DWORD*)col_2) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)));
|
|
|
|
|
|
|
|
|
|
// now shift to appropriate precision & divide by 2.
|
|
|
|
|
// << 3) / 2 == << 2
|
|
|
|
|
// << 2) / 2 == << 1
|
|
|
|
|
col_2->r = ((WORD) col_2->r << 2);
|
|
|
|
|
col_2->g = ((WORD) col_2->g << 1);
|
|
|
|
|
col_2->b = ((WORD) col_2->b << 2);
|
|
|
|
|
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
|
|
|
|
|
col_3->a = 0x00; //
|
|
|
|
|
col_3->r = 0x00; // random color to indicate alpha
|
|
|
|
|
col_3->g = 0xff;
|
|
|
|
|
col_3->b = 0xff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now shift orig color components
|
|
|
|
|
col_0->r <<= 3;
|
|
|
|
|
col_0->g <<= 2;
|
|
|
|
|
col_0->b <<= 3;
|
|
|
|
|
|
|
|
|
|
col_1->r <<= 3;
|
|
|
|
|
col_1->g <<= 2;
|
|
|
|
|
col_1->b <<= 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void GetColorBlockColors_m4(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
|
|
|
|
Color8888 * col_2, Color8888 * col_3,
|
|
|
|
|
WORD & wrd )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// m1 color extraction from 5-6-5
|
|
|
|
|
// m3 color math on DWORD before bit shift to full precision
|
|
|
|
|
wrd = pBlock->col0;
|
|
|
|
|
col_0->a = 0x00; // must set to 0 to avoid possible overflow & carry to next field in DWORD add
|
|
|
|
|
|
|
|
|
|
// extract r,g,b bits
|
|
|
|
|
col_0->b = (unsigned char) wrd & 0x1f; // 0x1f = 0001 1111 to mask out upper 3 bits
|
|
|
|
|
wrd >>= 5;
|
|
|
|
|
col_0->g = (unsigned char) wrd & 0x3f; // 0x3f = 0011 1111 to mask out upper 2 bits
|
|
|
|
|
wrd >>= 6;
|
|
|
|
|
col_0->r = (unsigned char) wrd & 0x1f;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// same for col # 2:
|
|
|
|
|
wrd = pBlock->col1;
|
|
|
|
|
col_1->a = 0x00; // must set to 0 to avoid possible overflow in DWORD add
|
|
|
|
|
|
|
|
|
|
// extract r,g,b bits
|
|
|
|
|
col_1->b = (unsigned char) wrd & 0x1f;
|
|
|
|
|
wrd >>= 5;
|
|
|
|
|
col_1->g = (unsigned char) wrd & 0x3f;
|
|
|
|
|
wrd >>= 6;
|
|
|
|
|
col_1->r = (unsigned char) wrd & 0x1f;
|
|
|
|
|
|
|
|
|
|
if (pBlock->col0 > pBlock->col1)
|
|
|
|
|
{
|
|
|
|
|
*((DWORD*)col_2) = ((*((DWORD*)col_0)) * 2 + (*((DWORD*)col_1)));
|
|
|
|
|
*((DWORD*)col_3) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)) * 2);
|
|
|
|
|
|
|
|
|
|
// shift to appropriate precision & divide by 3.
|
|
|
|
|
col_2->r = ((WORD) col_2->r << 3) / (WORD)3;
|
|
|
|
|
col_2->g = ((WORD) col_2->g << 2) / (WORD)3;
|
|
|
|
|
col_2->b = ((WORD) col_2->b << 3) / (WORD)3;
|
|
|
|
|
|
|
|
|
|
col_3->r = ((WORD) col_3->r << 3) / (WORD)3;
|
|
|
|
|
col_3->g = ((WORD) col_3->g << 2) / (WORD)3;
|
|
|
|
|
col_3->b = ((WORD) col_3->b << 3) / (WORD)3;
|
|
|
|
|
|
|
|
|
|
col_0->a = 0xff; // set appropriate alpha
|
|
|
|
|
col_1->a = 0xff;
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
col_3->a = 0xff;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*((DWORD*)col_2) = ((*((DWORD*)col_0)) + (*((DWORD*)col_1)));
|
|
|
|
|
|
|
|
|
|
// shift to appropriate precision & divide by 2.
|
|
|
|
|
// << 3) / 2 == << 2
|
|
|
|
|
// << 2) / 2 == << 1
|
|
|
|
|
col_2->r = ((WORD) col_2->r << 2);
|
|
|
|
|
col_2->g = ((WORD) col_2->g << 1);
|
|
|
|
|
col_2->b = ((WORD) col_2->b << 2);
|
|
|
|
|
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
|
|
|
|
|
col_3->a = 0x00; //
|
|
|
|
|
col_3->r = 0x00; // random color to indicate alpha
|
|
|
|
|
col_3->g = 0xff;
|
|
|
|
|
col_3->b = 0xff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// shift orig color components to full precision
|
|
|
|
|
col_0->r <<= 3;
|
|
|
|
|
col_0->g <<= 2;
|
|
|
|
|
col_0->b <<= 3;
|
|
|
|
|
|
|
|
|
|
col_1->r <<= 3;
|
|
|
|
|
col_1->g <<= 2;
|
|
|
|
|
col_1->b <<= 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void GetColorBlockColors_m1(DXTColBlock * pBlock, Color8888 * col_0, Color8888 * col_1,
|
|
|
|
|
Color8888 * col_2, Color8888 * col_3,
|
|
|
|
|
WORD & wrd )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// Method 1:
|
|
|
|
|
// Shifty method
|
|
|
|
|
wrd = pBlock->col0;
|
|
|
|
|
col_0->a = 0xff;
|
|
|
|
|
|
|
|
|
|
// extract r,g,b bits
|
|
|
|
|
col_0->b = (unsigned char) wrd;
|
|
|
|
|
col_0->b <<= 3; // shift to full precision
|
|
|
|
|
wrd >>= 5;
|
|
|
|
|
col_0->g = (unsigned char) wrd;
|
|
|
|
|
col_0->g <<= 2; // shift to full precision
|
|
|
|
|
wrd >>= 6;
|
|
|
|
|
col_0->r = (unsigned char) wrd;
|
|
|
|
|
col_0->r <<= 3; // shift to full precision
|
|
|
|
|
|
|
|
|
|
// same for col # 2:
|
|
|
|
|
wrd = pBlock->col1;
|
|
|
|
|
col_1->a = 0xff;
|
|
|
|
|
|
|
|
|
|
// extract r,g,b bits
|
|
|
|
|
col_1->b = (unsigned char) wrd;
|
|
|
|
|
col_1->b <<= 3; // shift to full precision
|
|
|
|
|
wrd >>= 5;
|
|
|
|
|
col_1->g = (unsigned char) wrd;
|
|
|
|
|
col_1->g <<= 2; // shift to full precision
|
|
|
|
|
wrd >>= 6;
|
|
|
|
|
col_1->r = (unsigned char) wrd;
|
|
|
|
|
col_1->r <<= 3; // shift to full precision
|
|
|
|
|
|
|
|
|
|
// use this for all but the super-freak math method
|
|
|
|
|
if (pBlock->col0 > pBlock->col1)
|
|
|
|
|
{
|
|
|
|
|
// Four-color block: derive the other two colors.
|
|
|
|
|
// 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
|
|
|
|
|
// These two bit codes correspond to the 2-bit fields
|
|
|
|
|
// stored in the 64-bit block.
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->r * 2 + (WORD) col_1->r) / 3;
|
|
|
|
|
// no +1 for rounding
|
|
|
|
|
// as bits have been shifted to 888
|
|
|
|
|
col_2->r = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->g * 2 + (WORD) col_1->g) / 3;
|
|
|
|
|
col_2->g = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->b * 2 + (WORD) col_1->b) / 3;
|
|
|
|
|
col_2->b = (BYTE)wrd;
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->r + (WORD) col_1->r * 2) / 3;
|
|
|
|
|
col_3->r = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->g + (WORD) col_1->g * 2) / 3;
|
|
|
|
|
col_3->g = (BYTE)wrd;
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->b + (WORD) col_1->b * 2) / 3;
|
|
|
|
|
col_3->b = (BYTE)wrd;
|
|
|
|
|
col_3->a = 0xff;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Three-color block: derive the other color.
|
|
|
|
|
// 00 = color_0, 01 = color_1, 10 = color_2,
|
|
|
|
|
// 11 = transparent.
|
|
|
|
|
// These two bit codes correspond to the 2-bit fields
|
|
|
|
|
// stored in the 64-bit block.
|
|
|
|
|
|
|
|
|
|
// explicit for each component, unlike some refrasts...
|
|
|
|
|
|
|
|
|
|
// Tracef("block has alpha\n");
|
|
|
|
|
|
|
|
|
|
wrd = ((WORD) col_0->r + (WORD) col_1->r) / 2;
|
|
|
|
|
col_2->r = (BYTE)wrd;
|
|
|
|
|
wrd = ((WORD) col_0->g + (WORD) col_1->g) / 2;
|
|
|
|
|
col_2->g = (BYTE)wrd;
|
|
|
|
|
wrd = ((WORD) col_0->b + (WORD) col_1->b) / 2;
|
|
|
|
|
col_2->b = (BYTE)wrd;
|
|
|
|
|
col_2->a = 0xff;
|
|
|
|
|
|
|
|
|
|
col_3->r = 0x00; // random color to indicate alpha
|
|
|
|
|
col_3->g = 0xff;
|
|
|
|
|
col_3->b = 0xff;
|
|
|
|
|
col_3->a = 0x00;
|
|
|
|
|
}
|
|
|
|
|
} // Get color block colors (...)
|
|
|
|
|
|
|
|
|
|
void CDXTCImage::Time_Decomp5_01(int ntimes, TimingInfo * info)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
info->m_nSamples = 0;
|
|
|
|
|
info->m_interval_sum.QuadPart = 0;
|
|
|
|
|
info->m_csName.Format("Timing decomp method 1: bit shift, for %d times\n", ntimes);
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < ntimes; n++)
|
|
|
|
|
{
|
|
|
|
|
QueryPerformanceCounter(& info->m_start_clk);
|
|
|
|
|
|
|
|
|
|
int xblocks, yblocks;
|
|
|
|
|
|
|
|
|
|
xblocks = m_DDSD.dwWidth / 4;
|
|
|
|
|
yblocks = m_DDSD.dwHeight / 4;
|
|
|
|
|
|
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
|
|
DWORD * pBase = (DWORD*) m_pDecompBytes;
|
|
|
|
|
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
|
|
|
|
|
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
|
|
|
|
|
|
|
|
|
|
DXTColBlock * pBlock;
|
|
|
|
|
DXTAlphaBlock3BitLinear * pAlphaBlock;
|
|
|
|
|
|
|
|
|
|
Color8888 col_0, col_1, col_2, col_3;
|
|
|
|
|
WORD wrd;
|
|
|
|
|
|
|
|
|
|
// fill alphazero with appropriate value to zero out alpha when
|
|
|
|
|
// alphazero is ANDed with the image color 32 bit DWORD:
|
|
|
|
|
col_0.a = 0;
|
|
|
|
|
col_0.r = col_0.g = col_0.b = 0xff;
|
|
|
|
|
DWORD alphazero = *((DWORD*) &col_0);
|
|
|
|
|
|
|
|
|
|
// ** See DecompressDXT5 code for comments!!
|
|
|
|
|
for (j = 0; j < yblocks; ++j)
|
|
|
|
|
{
|
|
|
|
|
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
|
|
|
|
|
for (i = 0; i < xblocks; ++i, ++pBlock)
|
|
|
|
|
{
|
|
|
|
|
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
|
|
|
|
|
pBlock++;
|
|
|
|
|
|
|
|
|
|
GetColorBlockColors_m1(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
|
|
|
|
|
|
|
|
|
|
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
|
|
|
|
|
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
|
|
|
|
|
(DWORD*)&col_2, (DWORD*)&col_3);
|
|
|
|
|
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QueryPerformanceCounter(& info->m_end_clk);
|
|
|
|
|
|
|
|
|
|
info->m_nSamples ++;
|
|
|
|
|
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CDXTCImage::Time_Decomp5_02(int ntimes, TimingInfo * info)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
info->m_nSamples = 0;
|
|
|
|
|
info->m_interval_sum.QuadPart = 0;
|
|
|
|
|
info->m_csName.Format("Timing decomp method 2: bit field struct, for %d times\n", ntimes);
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < ntimes; n++)
|
|
|
|
|
{
|
|
|
|
|
QueryPerformanceCounter(& info->m_start_clk);
|
|
|
|
|
|
|
|
|
|
int xblocks, yblocks;
|
|
|
|
|
xblocks = m_DDSD.dwWidth / 4;
|
|
|
|
|
yblocks = m_DDSD.dwHeight / 4;
|
|
|
|
|
int i,j;
|
|
|
|
|
DWORD * pBase = (DWORD*) m_pDecompBytes;
|
|
|
|
|
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
|
|
|
|
|
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
|
|
|
|
|
DXTColBlock * pBlock;
|
|
|
|
|
DXTAlphaBlock3BitLinear * pAlphaBlock;
|
|
|
|
|
Color8888 col_0, col_1, col_2, col_3;
|
|
|
|
|
WORD wrd;
|
|
|
|
|
// fill alphazero with appropriate value to zero out alpha when
|
|
|
|
|
// alphazero is ANDed with the image color 32 bit DWORD:
|
|
|
|
|
col_0.a = 0;
|
|
|
|
|
col_0.r = col_0.g = col_0.b = 0xff;
|
|
|
|
|
DWORD alphazero = *((DWORD*) &col_0);
|
|
|
|
|
|
|
|
|
|
// ** See DecompressDXT5 code for comments!!
|
|
|
|
|
for (j = 0; j < yblocks; ++j)
|
|
|
|
|
{
|
|
|
|
|
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
|
|
|
|
|
for (i = 0; i < xblocks; ++i, ++pBlock)
|
|
|
|
|
{
|
|
|
|
|
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
|
|
|
|
|
pBlock++;
|
|
|
|
|
|
|
|
|
|
GetColorBlockColors_m2(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
|
|
|
|
|
|
|
|
|
|
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
|
|
|
|
|
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
|
|
|
|
|
(DWORD*)&col_2, (DWORD*)&col_3);
|
|
|
|
|
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QueryPerformanceCounter(& info->m_end_clk);
|
|
|
|
|
|
|
|
|
|
info->m_nSamples ++;
|
|
|
|
|
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CDXTCImage::Time_Decomp5_03(int ntimes, TimingInfo * info)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
info->m_nSamples = 0;
|
|
|
|
|
info->m_interval_sum.QuadPart = 0;
|
|
|
|
|
info->m_csName.Format("Timing decomp method 3: bit field struct w/ pre-shift math, for %d times\n", ntimes);
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < ntimes; n++)
|
|
|
|
|
{
|
|
|
|
|
QueryPerformanceCounter(& info->m_start_clk);
|
|
|
|
|
|
|
|
|
|
int xblocks, yblocks;
|
|
|
|
|
xblocks = m_DDSD.dwWidth / 4;
|
|
|
|
|
yblocks = m_DDSD.dwHeight / 4;
|
|
|
|
|
int i,j;
|
|
|
|
|
DWORD * pBase = (DWORD*) m_pDecompBytes;
|
|
|
|
|
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
|
|
|
|
|
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
|
|
|
|
|
DXTColBlock * pBlock;
|
|
|
|
|
DXTAlphaBlock3BitLinear * pAlphaBlock;
|
|
|
|
|
Color8888 col_0, col_1, col_2, col_3;
|
|
|
|
|
WORD wrd;
|
|
|
|
|
|
|
|
|
|
// fill alphazero with appropriate value to zero out alpha when
|
|
|
|
|
// alphazero is ANDed with the image color 32 bit DWORD:
|
|
|
|
|
col_0.a = 0;
|
|
|
|
|
col_0.r = col_0.g = col_0.b = 0xff;
|
|
|
|
|
DWORD alphazero = *((DWORD*) &col_0);
|
|
|
|
|
|
|
|
|
|
// ** See DecompressDXT5 code for comments!!
|
|
|
|
|
for (j = 0; j < yblocks; ++j)
|
|
|
|
|
{
|
|
|
|
|
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
|
|
|
|
|
for (i = 0; i < xblocks; ++i, ++pBlock)
|
|
|
|
|
{
|
|
|
|
|
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
|
|
|
|
|
pBlock++;
|
|
|
|
|
|
|
|
|
|
GetColorBlockColors_m3(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
|
|
|
|
|
|
|
|
|
|
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
|
|
|
|
|
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
|
|
|
|
|
(DWORD*)&col_2, (DWORD*)&col_3);
|
|
|
|
|
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QueryPerformanceCounter(& info->m_end_clk);
|
|
|
|
|
|
|
|
|
|
info->m_nSamples ++;
|
|
|
|
|
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CDXTCImage::Time_Decomp5_04(int ntimes, TimingInfo * info)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
info->m_nSamples = 0;
|
|
|
|
|
info->m_interval_sum.QuadPart = 0;
|
|
|
|
|
info->m_csName.Format("Timing decomp method 4: shift extract w/ pre-shift math, for %d times\n", ntimes);
|
|
|
|
|
|
|
|
|
|
QueryPerformanceCounter(& info->m_start_clk);
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < ntimes; n++)
|
|
|
|
|
{
|
|
|
|
|
int xblocks, yblocks;
|
|
|
|
|
xblocks = m_DDSD.dwWidth / 4;
|
|
|
|
|
yblocks = m_DDSD.dwHeight / 4;
|
|
|
|
|
int i,j;
|
|
|
|
|
DWORD * pBase = (DWORD*) m_pDecompBytes;
|
|
|
|
|
DWORD * pImPos = (DWORD*) pBase; // pos in decompressed data
|
|
|
|
|
WORD * pPos = (WORD*) m_pCompBytes; // pos in compressed data
|
|
|
|
|
DXTColBlock * pBlock;
|
|
|
|
|
DXTAlphaBlock3BitLinear * pAlphaBlock;
|
|
|
|
|
Color8888 col_0, col_1, col_2, col_3;
|
|
|
|
|
WORD wrd;
|
|
|
|
|
// fill alphazero with appropriate value to zero out alpha when
|
|
|
|
|
// alphazero is ANDed with the image color 32 bit DWORD:
|
|
|
|
|
col_0.a = 0;
|
|
|
|
|
col_0.r = col_0.g = col_0.b = 0xff;
|
|
|
|
|
DWORD alphazero = *((DWORD*) &col_0);
|
|
|
|
|
|
|
|
|
|
// ** See DecompressDXT5 code for comments!!
|
|
|
|
|
for (j = 0; j < yblocks; ++j)
|
|
|
|
|
{
|
|
|
|
|
pBlock = (DXTColBlock*) ((DWORD)m_pCompBytes + j * xblocks * 16);
|
|
|
|
|
for (i = 0; i < xblocks; ++i, ++pBlock)
|
|
|
|
|
{
|
|
|
|
|
pAlphaBlock = (DXTAlphaBlock3BitLinear*) pBlock;
|
|
|
|
|
pBlock++;
|
|
|
|
|
|
|
|
|
|
GetColorBlockColors_m4(pBlock, &col_0, &col_1, &col_2, &col_3, wrd);
|
|
|
|
|
|
|
|
|
|
pImPos = (DWORD*)((DWORD)pBase + i*16 + (j*4) * m_nWidth * 4);
|
|
|
|
|
DecodeColorBlock(pImPos, pBlock, m_nWidth, (DWORD*)&col_0, (DWORD*)&col_1,
|
|
|
|
|
(DWORD*)&col_2, (DWORD*)&col_3);
|
|
|
|
|
DecodeAlpha3BitLinear(pImPos, pAlphaBlock, m_nWidth, alphazero);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QueryPerformanceCounter(& info->m_end_clk);
|
|
|
|
|
|
|
|
|
|
info->m_nSamples = ntimes;
|
|
|
|
|
info->m_interval_sum.QuadPart += info->m_end_clk.QuadPart - info->m_start_clk.QuadPart;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|