windows-nt/Source/XPSP1/NT/multimedia/directx/dxg/ref8/common/dxtn.cpp
2020-09-26 16:20:57 +08:00

255 lines
7.3 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Copyright (C) Microsoft Corporation, 1998.
//
// dxtn.cpp
//
// Direct3D Reference Rasterizer - DXTn texture compression functions
//
///////////////////////////////////////////////////////////////////////////////
#include "pch.cpp"
// Primary color components (use DirextX byte ordering)
#undef RED
#define RED 0
#undef GRN
#define GRN 1
#undef BLU
#define BLU 2
#undef ALFA
#define ALFA 3
typedef struct
{
float rgba[4];
} FCOLOR; // internal color format
//
// Processing all primaries is such a common idiom
// that we define a macro for this action.
// Any self-respecting C compiler should easily optimize
// this by unrolling the loop!
//
#define ForAllPrimaries for( primary = 0; primary < NUM_PRIMARIES; ++primary)
// Similarly, processing all pixels in a block is a common idiom.
#define ForAllPixels for(pixel=0; pixel < DXT_BLOCK_PIXELS; ++pixel)
#define NUM_PRIMARIES 3
#define NUM_COMPONENTS 4
//
// Quantization constants for RGB565
//
#define PRIMARY_BITS 8
#define RED_BITS 5
#define GRN_BITS 6
#define BLU_BITS 5
#define RED_SHIFT (PRIMARY_BITS-RED_BITS)
#define GRN_SHIFT (PRIMARY_BITS-GRN_BITS)
#define BLU_SHIFT (PRIMARY_BITS-BLU_BITS)
#if 0
#define RED_MASK 0xf8
#define GRN_MASK 0xfc
#define BLU_MASK 0xf8
#endif
// Weighting for each primary based on NTSC luminance
static float wtPrimary[NUM_PRIMARIES] =
{
0.0820f, // blue
0.6094f, // green
0.3086f // red
};
//-----------------------------------------------------------------------------
//
// unpack a fixed point color
//
//-----------------------------------------------------------------------------
static void RGBToColor (RGB565 *prgb, DXT_COLOR *pcolor)
{
WORD rgb;
DXT_COLOR color;
rgb = *((WORD *)prgb);
// pick off bits in groups of 5, 6, and 5
color.rgba[BLU] = (unsigned char) rgb;
rgb >>= BLU_BITS;
color.rgba[GRN] = (unsigned char) rgb;
rgb >>= GRN_BITS;
color.rgba[RED] = (unsigned char) rgb;
// shift primaries into the appropriate LSBs
color.rgba[BLU] <<= BLU_SHIFT;
color.rgba[GRN] <<= GRN_SHIFT;
color.rgba[RED] <<= RED_SHIFT;
// replicate primaries MSBs into LSBs
color.rgba[BLU] |= color.rgba[BLU] >> BLU_BITS;
color.rgba[GRN] |= color.rgba[GRN] >> GRN_BITS;
color.rgba[RED] |= color.rgba[RED] >> RED_BITS;
*pcolor = color;
}
//-----------------------------------------------------------------------------
//
// DecodeBlockRGB - decompress a color block
//
//-----------------------------------------------------------------------------
void DecodeBlockRGB (DXTBlockRGB *pblockSrc, DXT_COLOR colorDst[DXT_BLOCK_PIXELS])
{
int lev;
DXT_COLOR clut[4];
PIXBM pixbm;
int pixel;
int primary;
// if source block is invalid, ...
if (pblockSrc == NULL)
return;
// determine the number of color levels in the block
lev = (pblockSrc->rgb0 <= pblockSrc->rgb1) ? 2 : 3;
// Fill extrema values into pixel code lookup table.
RGBToColor(&pblockSrc->rgb0, &clut[0]);
RGBToColor(&pblockSrc->rgb1, &clut[1]);
clut[0].rgba[ALFA] =
clut[1].rgba[ALFA] =
clut[2].rgba[ALFA] = 255;
if (lev == 3)
{ // No transparency info present, all color info.
ForAllPrimaries
{
WORD temp0 = clut[0].rgba[primary]; // jvanaken fixed overflow bug
WORD temp1 = clut[1].rgba[primary];
clut[2].rgba[primary] = (BYTE)((2*temp0 + temp1 + 1)/3);
clut[3].rgba[primary] = (BYTE)((temp0 + 2*temp1 + 1)/3);
}
clut[3].rgba[ALFA] = 255;
}
else
{ // transparency info.
ForAllPrimaries
{
WORD temp0 = clut[0].rgba[primary]; // jvanaken fixed overflow bug
WORD temp1 = clut[1].rgba[primary];
clut[2].rgba[primary] = (BYTE)((temp0 + temp1)/2);
clut[3].rgba[primary] = 0; // jvanaken added this
}
clut[3].rgba[ALFA] = 0;
}
// munge a local copy
pixbm = pblockSrc->pixbm;
// Look up the actual pixel color in the table.
ForAllPixels
{
// lookup color from pixel bitmap
ForAllPrimaries
colorDst[pixel].rgba[primary] = clut[pixbm & 3].rgba[primary];
colorDst[pixel].rgba[ALFA] = clut[pixbm & 3].rgba[ALFA];
// prepare to extract next index
pixbm >>= 2;
}
}
//-----------------------------------------------------------------------------
// DecodeBlockAlpha4 - decompress a block with alpha at 4 BPP
//-----------------------------------------------------------------------------
void DecodeBlockAlpha4(DXTBlockAlpha4 *pblockSrc, DXT_COLOR colorDst[DXT_BLOCK_PIXELS])
{
int row, col;
WORD alpha;
DecodeBlockRGB(&pblockSrc->rgb, colorDst);
for (row = 0; row < 4; ++row)
{
alpha = pblockSrc->alphabm[row];
for (col = 0; col < 4; ++col)
{
colorDst[4 * row + col].rgba[ALFA] =
((alpha & 0xf) << 4)
| (alpha & 0xf);
alpha >>= 4;
}
}
}
//-----------------------------------------------------------------------------
//
// DecodeBlockAlpha3 - decompress a block with alpha at 3 BPP
//
//-----------------------------------------------------------------------------
void DecodeBlockAlpha3(DXTBlockAlpha3 *pblockSrc, DXT_COLOR colorDst[DXT_BLOCK_PIXELS])
{
int pixel;
int alpha[8]; // alpha lookup table
DWORD dwBM = 0; // alpha bitmap in DWORD cache
DecodeBlockRGB(&pblockSrc->rgb, colorDst);
alpha[0] = pblockSrc->alpha0;
alpha[1] = pblockSrc->alpha1;
if (alpha[0] > alpha[1]) // 8 alpha ramp
{ // interpolate intermediate colors
alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7;
alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7;
alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7;
alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7;
alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7;
alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7;
}
else // else 6 alpha ramp with 0 and 255
{ // interpolate intermediate colors
alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5;
alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5;
alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5;
alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5;
alpha[6] = 0;
alpha[7] = 255;
}
ForAllPixels
{ // reload bitmap dword cache every 8 pixels
if ((pixel & 7) == 0)
{
if (pixel == 0)
{ // pack 3 bytes into dword
dwBM = pblockSrc->alphabm[2];
dwBM <<= 8;
dwBM |= pblockSrc->alphabm[1];
dwBM <<= 8;
dwBM |= pblockSrc->alphabm[0];
}
else // pixel == 8
{ // pack 3 bytes into dword
dwBM = pblockSrc->alphabm[5];
dwBM <<= 8;
dwBM |= pblockSrc->alphabm[4];
dwBM <<= 8;
dwBM |= pblockSrc->alphabm[3];
}
}
// unpack bitmap dword 3 bits at a time
colorDst[pixel].rgba[ALFA] = (BYTE)alpha[(dwBM & 7)];
dwBM >>= 3;
}
}
///////////////////////////////////////////////////////////////////////////////
// end