You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
10 KiB
302 lines
10 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) Microsoft Corporation, 1998.
|
|
//
|
|
// texmap.cpp
|
|
//
|
|
// Direct3D Reference Rasterizer - Texture Map Access Methods
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
inline UINT8 CLAMP_BYTE(double f)
|
|
{
|
|
if (f > 255.0) return 255;
|
|
if (f < 0.0) return 0;
|
|
return (BYTE) f;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// TexelFromBlock - decompress a color block and obtain texel color
|
|
//-----------------------------------------------------------------------------
|
|
UINT32 TexelFromBlock(RRSurfaceType surfType, char *pblockSrc,
|
|
int x, int y)
|
|
{
|
|
UINT32 index = ((y & 0x3)<<2) + (x & 0x3);
|
|
DDRGBA colorDst[DXT_BLOCK_PIXELS];
|
|
|
|
switch(surfType)
|
|
{
|
|
case RR_STYPE_DXT1:
|
|
DecodeBlockRGB((DXTBlockRGB *)pblockSrc, (DXT_COLOR *)colorDst);
|
|
break;
|
|
case RR_STYPE_DXT2:
|
|
case RR_STYPE_DXT3:
|
|
DecodeBlockAlpha4((DXTBlockAlpha4 *)pblockSrc,
|
|
(DXT_COLOR *)colorDst);
|
|
break;
|
|
case RR_STYPE_DXT4:
|
|
case RR_STYPE_DXT5:
|
|
DecodeBlockAlpha3((DXTBlockAlpha3 *)pblockSrc,
|
|
(DXT_COLOR *)colorDst);
|
|
break;
|
|
}
|
|
|
|
return RGBA_MAKE(colorDst[index].red,
|
|
colorDst[index].green,
|
|
colorDst[index].blue,
|
|
colorDst[index].alpha);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// ReadTexelColor - Reads texel from texture map at given LOD; converts to
|
|
// RRColor format, applying palette if necessary; also performs colorkey by
|
|
// zero-ing out alpha
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
RRTexture::ReadColor(
|
|
INT32 iX, INT32 iY, INT32 iLOD,
|
|
RRColor& Texel, BOOL &bColorKeyMatched )
|
|
{
|
|
if ( (iLOD > m_cLOD) && !(m_uFlags & RR_TEXTURE_ENVMAP) )
|
|
{
|
|
return;
|
|
}
|
|
if ( NULL == m_pTextureBits[iLOD] ) { return; }
|
|
|
|
char* pSurfaceBits =
|
|
PixelAddress( iX, iY, m_pTextureBits[iLOD], m_iPitch[iLOD], m_SurfType );
|
|
|
|
switch ( m_SurfType )
|
|
{
|
|
default:
|
|
Texel.ConvertFrom( m_SurfType, pSurfaceBits );
|
|
break;
|
|
|
|
case RR_STYPE_PALETTE8:
|
|
{
|
|
UINT8 uIndex = *((UINT8*)pSurfaceBits);
|
|
UINT32 uTexel = *( (UINT32*)(m_pPalette) + uIndex );
|
|
Texel = RGBA_MAKE(
|
|
(uTexel>> 0) & 0xff,
|
|
(uTexel>> 8) & 0xff,
|
|
(uTexel>>16) & 0xff,
|
|
(uTexel>>24) & 0xff);
|
|
if ( !( m_uFlags & RR_TEXTURE_ALPHAINPALETTE ) ) Texel.A = 1.f;
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_PALETTE4:
|
|
{
|
|
UINT8 uIndex = *((INT8*)pSurfaceBits);
|
|
if ((iX & 1) == 0) { uIndex &= 0xf; }
|
|
else { uIndex >>= 4; }
|
|
UINT32 uTexel = *( (UINT32*)(m_pPalette) + uIndex );
|
|
Texel = RGBA_MAKE(
|
|
(uTexel>> 0) & 0xff,
|
|
(uTexel>> 8) & 0xff,
|
|
(uTexel>>16) & 0xff,
|
|
(uTexel>>24) & 0xff);
|
|
if ( !( m_uFlags & RR_TEXTURE_ALPHAINPALETTE ) ) Texel.A = 1.f;
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_UYVY:
|
|
case RR_STYPE_YUY2:
|
|
// Converts a given YUV (8bits each) to RGB scaled between 0 and 255
|
|
// These are using the YCrCb to RGB algorithms given on page 30
|
|
// in "VIDEO DEMYSTIFIED" by Keith Jack
|
|
// ISBN#: 1-878707-09-4
|
|
// IN PC graphics, even though they call it YUV, it is really YCrCb
|
|
// formats that are used by most framegrabbers etc. Hence the pixel
|
|
// data we will obtain in these YUV surfaces will most likely be this
|
|
// and not the original YUV which is actually used in PAL broadcast
|
|
// only (NTSC uses YIQ). So really, U should be called Cb (Blue color
|
|
// difference) and V should be called Cr (Red color difference)
|
|
//
|
|
// These equations are meant to handle the following ranges
|
|
// (from the same book):
|
|
// Y (16 to 235), U and V (16 to 240, 128 = zero)
|
|
// -----------
|
|
// Y U V
|
|
// -----------
|
|
// White : 180 128 128
|
|
// Black : 16 128 128
|
|
// Red : 65 100 212
|
|
// Green : 112 72 58
|
|
// Blue : 35 212 114
|
|
// Yellow : 162 44 142
|
|
// Cyan : 131 156 44
|
|
// Magenta: 84 184 198
|
|
// -----------
|
|
// It is assumed that the gamma corrected RGB range is (0 - 255)
|
|
//
|
|
// UYVY: U0Y0 V0Y1 U2Y2 V2Y3 (low byte always has current Y)
|
|
// If iX is even, hight-byte has current U (Cb)
|
|
// If iX is odd, hight-byte has previous V (Cr)
|
|
//
|
|
// YUY2: Y0U0 Y1V0 Y2U2 Y3V2 (high byte always has current Y)
|
|
// (UYVY bytes flipped)
|
|
//
|
|
// In this algorithm, we use U and V values from two neighboring
|
|
// pixels
|
|
{
|
|
UINT8 Y, U, V;
|
|
UINT16 u16Curr = *((UINT16*)pSurfaceBits);
|
|
UINT16 u16ForU = 0; // Extract U from this
|
|
UINT16 u16ForV = 0; // Extract V from this
|
|
|
|
// By default we assume YUY2. Change it later if it is UYVY
|
|
int uvShift = 8;
|
|
int yShift = 0;
|
|
|
|
if (m_SurfType == RR_STYPE_UYVY)
|
|
{
|
|
uvShift = 0;
|
|
yShift = 8;
|
|
}
|
|
|
|
if ((iX & 1) == 0)
|
|
{
|
|
// Current U available
|
|
u16ForU = u16Curr;
|
|
|
|
// Obtain V from the next pixel
|
|
if ( (iX < (m_iWidth >> iLOD)) || (m_uFlags & RR_TEXTURE_ENVMAP) )
|
|
{
|
|
u16ForV = *((UINT16*)PixelAddress( iX+1, iY,
|
|
m_pTextureBits[iLOD],
|
|
m_iPitch[iLOD],
|
|
m_SurfType ));
|
|
}
|
|
else
|
|
{
|
|
// This case should not be hit because the texture
|
|
// width is even (actually, a power of two)
|
|
_ASSERTa(0, "iX exceeds width", u16ForV = u16Curr;)
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Current V available
|
|
u16ForV = u16Curr;
|
|
|
|
// Obtain U from the previous pixel
|
|
if (iX > 0)
|
|
{
|
|
u16ForU = *((UINT16*)PixelAddress( iX-1, iY,
|
|
m_pTextureBits[iLOD],
|
|
m_iPitch[iLOD],
|
|
m_SurfType ));
|
|
}
|
|
else
|
|
{
|
|
// This case should not be hit because the texture
|
|
// width is even (actually, a power of two)
|
|
_ASSERTa(0, "iX is negative", u16ForU = u16Curr;)
|
|
}
|
|
}
|
|
|
|
Y = (u16Curr >> yShift) & 0xff;
|
|
U = (u16ForU >> uvShift) & 0xff;
|
|
V = (u16ForV >> uvShift) & 0xff;
|
|
|
|
Texel = RGB_MAKE(
|
|
CLAMP_BYTE(1.164*(Y-16) + 1.596*(V-128)),
|
|
CLAMP_BYTE(1.164*(Y-16) - 0.813*(V-128) - 0.391*(U-128)),
|
|
CLAMP_BYTE(1.164*(Y-16) + 2.018*(U-128))
|
|
);
|
|
Texel.A = 1.f;
|
|
}
|
|
break;
|
|
|
|
// S3 compressed formats:
|
|
// We have the address to the block, now extract the actual color
|
|
case RR_STYPE_DXT1:
|
|
case RR_STYPE_DXT2:
|
|
case RR_STYPE_DXT3:
|
|
case RR_STYPE_DXT4:
|
|
case RR_STYPE_DXT5:
|
|
Texel = TexelFromBlock(m_SurfType, pSurfaceBits, iX, iY);
|
|
break;
|
|
}
|
|
|
|
// colorkey (only supported for legacy behavior)
|
|
if ( m_bDoColorKeyKill || m_bDoColorKeyZero )
|
|
{
|
|
DWORD dwBits;
|
|
switch ( m_SurfType )
|
|
{
|
|
default:
|
|
case RR_STYPE_NULL:
|
|
return; // don't colorkey unknown or null surfaces
|
|
|
|
case RR_STYPE_PALETTE4:
|
|
{
|
|
UINT8 uIndex = *((INT8*)pSurfaceBits);
|
|
if ((iX & 1) == 0) { uIndex &= 0xf; }
|
|
else { uIndex >>= 4; }
|
|
dwBits = (DWORD)uIndex;
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_L8:
|
|
case RR_STYPE_PALETTE8:
|
|
case RR_STYPE_B2G3R3:
|
|
case RR_STYPE_L4A4:
|
|
{
|
|
UINT8 uBits = *((UINT8*)pSurfaceBits);
|
|
dwBits = (DWORD)uBits;
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_B5G6R5:
|
|
case RR_STYPE_B5G5R5:
|
|
case RR_STYPE_B5G5R5A1:
|
|
case RR_STYPE_B4G4R4A4:
|
|
case RR_STYPE_L8A8:
|
|
case RR_STYPE_B2G3R3A8:
|
|
{
|
|
UINT16 uBits = *((UINT16*)pSurfaceBits);
|
|
dwBits = (DWORD)uBits;
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_B8G8R8:
|
|
{
|
|
UINT32 uBits = 0;
|
|
uBits |= ( *((UINT8*)pSurfaceBits+0) ) << 0;
|
|
uBits |= ( *((UINT8*)pSurfaceBits+1) ) << 8;
|
|
uBits |= ( *((UINT8*)pSurfaceBits+2) ) << 16;
|
|
dwBits = (DWORD)uBits;
|
|
}
|
|
break;
|
|
|
|
case RR_STYPE_B8G8R8A8:
|
|
case RR_STYPE_B8G8R8X8:
|
|
{
|
|
UINT32 uBits = *((UINT32*)pSurfaceBits);
|
|
dwBits = (DWORD)uBits;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( dwBits == m_dwColorKey )
|
|
{
|
|
bColorKeyMatched = TRUE;
|
|
if (m_bDoColorKeyZero)
|
|
{
|
|
Texel.A = 0.F;
|
|
Texel.R = 0.F;
|
|
Texel.G = 0.F;
|
|
Texel.B = 0.F;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// end
|