#include "sis_context.h"
#include "sis_state.h"
#include "swrast/swrast.h"
#include "mmath.h"
static GLint convertFtToFogFt( GLfloat dwInValue );
void
sisDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
__GLSiSHardware *prev = &smesa->prev;
__GLSiSHardware *current = &smesa->current;
float fArg;
GLint fogColor;
switch (pname)
{
case GL_FOG_MODE:
current->hwFog &= ~MASK_FogMode;
switch (ctx->Fog.Mode)
{
case GL_LINEAR:
current->hwFog |= FOGMODE_LINEAR;
break;
case GL_EXP:
current->hwFog |= FOGMODE_EXP;
break;
case GL_EXP2:
current->hwFog |= FOGMODE_EXP2;
break;
}
if (current->hwFog != prev->hwFog) {
prev->hwFog = current->hwFog;
smesa->GlobalFlag |= GFLAG_FOGSETTING;
}
break;
case GL_FOG_DENSITY:
current->hwFogDensity = convertFtToFogFt( ctx->Fog.Density );
if (current->hwFogDensity != prev->hwFogDensity) {
prev->hwFogDensity = current->hwFogDensity;
smesa->GlobalFlag |= GFLAG_FOGSETTING;
}
break;
case GL_FOG_START:
case GL_FOG_END:
fArg = 1.0 / (ctx->Fog.End - ctx->Fog.Start);
current->hwFogInverse = doFPtoFixedNoRound( fArg, 10 );
if (pname == GL_FOG_END)
{
if (smesa->Chipset == PCI_CHIP_SIS300)
current->hwFogFar = doFPtoFixedNoRound( ctx->Fog.End, 10 );
else
current->hwFogFar = doFPtoFixedNoRound( ctx->Fog.End, 6 );
}
if (current->hwFogFar != prev->hwFogFar ||
current->hwFogInverse != prev->hwFogInverse)
{
prev->hwFogFar = current->hwFogFar;
prev->hwFogInverse = current->hwFogInverse;
smesa->GlobalFlag |= GFLAG_FOGSETTING;
}
break;
case GL_FOG_INDEX:
break;
case GL_FOG_COLOR:
fogColor = FLOAT_TO_UBYTE( ctx->Fog.Color[0] ) << 16;
fogColor |= FLOAT_TO_UBYTE( ctx->Fog.Color[1] ) << 8;
fogColor |= FLOAT_TO_UBYTE( ctx->Fog.Color[2] );
current->hwFog &= 0xff000000;
current->hwFog |= fogColor;
if (current->hwFog != prev->hwFog) {
prev->hwFog = current->hwFog;
smesa->GlobalFlag |= GFLAG_FOGSETTING;
}
break;
}
}
GLint
doFPtoFixedNoRound( GLfloat dwInValue, int nFraction )
{
GLint dwMantissa;
int nTemp;
union { int i; float f; } u;
GLint val;
u.f = dwInValue;
val = u.i;
if (val == 0)
return 0;
nTemp = (int) (val & 0x7F800000) >> 23;
nTemp = nTemp - 127 + nFraction - 23;
dwMantissa = (val & 0x007FFFFF) | 0x00800000;
if (nTemp < -25)
return 0;
if (nTemp > 0)
dwMantissa <<= nTemp;
else {
nTemp = -nTemp;
dwMantissa >>= nTemp;
}
if (val & 0x80000000)
dwMantissa = ~dwMantissa + 1;
return dwMantissa;
}
static GLint
convertFtToFogFt( GLfloat dwInValue )
{
GLint dwMantissa, dwExp;
GLint dwRet;
union { int i; float f; } u;
GLint val;
u.f = dwInValue;
val = u.i;
if (val == 0)
return 0;
dwExp = (val & 0x7F800000) >> 23;
dwExp -= 63;
if (dwExp < 0)
return 0;
if (dwExp <= 0x7F)
dwMantissa = (val & 0x007FFFFF) >> (23 - 10);
else {
dwExp = 0x7F;
dwMantissa = 0x3FF;
}
dwRet = (val & 0x80000000) >> (31 - 17);
dwRet |= (dwExp << 10) | dwMantissa;
return dwRet;
}