|
|
//----------------------------------------------------------------------------
//
// attrs.cpp
//
// Cross-platform attribute handling functions.
//
// Copyright (C) Microsoft Corporation, 1997.
//
//----------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
//----------------------------------------------------------------------------
//
// AddFloatAttrs_Any
//
// Adds a set of attribute deltas to an ATTRSET.
// Handles any set of attributes via USED flags.
//
//----------------------------------------------------------------------------
void FASTCALL AddFloatAttrs_Any(PATTRSET pAttr, PATTRSET pDelta, PSETUPCTX pStpCtx) { pAttr->pSurface += pDelta->ipSurface; pAttr->pZ += pDelta->ipZ;
if (pStpCtx->uFlags & PRIMSF_Z_USED) { pAttr->fZ += pDelta->fZ; }
if (pStpCtx->uFlags & PRIMSF_TEX_USED) { pAttr->fOoW += pDelta->fOoW;
pAttr->fUoW1 += pDelta->fUoW1; pAttr->fVoW1 += pDelta->fVoW1; }
if (pStpCtx->uFlags & PRIMSF_TEX2_USED) { pAttr->fUoW2 += pDelta->fUoW2; pAttr->fVoW2 += pDelta->fVoW2; }
if (pStpCtx->uFlags & PRIMSF_DIFF_USED) { pAttr->fB += pDelta->fB; pAttr->fG += pDelta->fG; pAttr->fR += pDelta->fR; pAttr->fA += pDelta->fA; } else if (pStpCtx->uFlags & PRIMSF_DIDX_USED) { pAttr->fDIdx += pDelta->fDIdx; pAttr->fDIdxA += pDelta->fDIdxA; }
if (pStpCtx->uFlags & PRIMSF_SPEC_USED) { pAttr->fBS += pDelta->fBS; pAttr->fGS += pDelta->fGS; pAttr->fRS += pDelta->fRS; }
if (pStpCtx->uFlags & PRIMSF_LOCAL_FOG_USED) { pAttr->fFog += pDelta->fFog; } }
//----------------------------------------------------------------------------
//
// AddScaledFloatAttrs_Any_Either
//
// Scales and adds a set of attribute deltas to an ATTRSET.
// Handles any set of attributes via USED flags.
// Uses PWL support.
//
//----------------------------------------------------------------------------
void FASTCALL AddScaledFloatAttrs_Any_Either(PATTRSET pAttr, PATTRSET pDelta, PSETUPCTX pStpCtx, INT iScale) { FLOAT fScale = (FLOAT)iScale;
pAttr->pSurface += pDelta->ipSurface * iScale; pAttr->pZ += pDelta->ipZ * iScale;
if (pStpCtx->uFlags & PRIMSF_Z_USED) { #ifdef PWL_FOG
if (pStpCtx->uPwlFlags & PWL_NEXT_FOG) { pAttr->fZ = pStpCtx->fNextZ; } else #endif
{ pAttr->fZ += pDelta->fZ * fScale; } }
if (pStpCtx->uFlags & PRIMSF_TEX_USED) { if (pStpCtx->uPwlFlags & PWL_NEXT_LOD) { pAttr->fOoW = pStpCtx->fNextOoW; pAttr->fUoW1 = pStpCtx->fNextUoW1; pAttr->fVoW1 = pStpCtx->fNextVoW1; } else { pAttr->fOoW += pDelta->fOoW * fScale; pAttr->fUoW1 += pDelta->fUoW1 * fScale; pAttr->fVoW1 += pDelta->fVoW1 * fScale; } }
if (pStpCtx->uFlags & PRIMSF_TEX2_USED) { pAttr->fUoW2 += pDelta->fUoW2 * fScale; pAttr->fVoW2 += pDelta->fVoW2 * fScale; }
if (pStpCtx->uFlags & PRIMSF_DIFF_USED) { pAttr->fB += pDelta->fB * fScale; pAttr->fG += pDelta->fG * fScale; pAttr->fR += pDelta->fR * fScale; pAttr->fA += pDelta->fA * fScale; } else if (pStpCtx->uFlags & PRIMSF_DIDX_USED) { pAttr->fDIdx += pDelta->fDIdx * fScale; pAttr->fDIdxA += pDelta->fDIdxA * fScale; }
if (pStpCtx->uFlags & PRIMSF_SPEC_USED) { pAttr->fBS += pDelta->fBS * fScale; pAttr->fGS += pDelta->fGS * fScale; pAttr->fRS += pDelta->fRS * fScale; }
if (pStpCtx->uFlags & PRIMSF_LOCAL_FOG_USED) { pAttr->fFog += pDelta->fFog * fScale; } }
//----------------------------------------------------------------------------
//
// FillSpanFloatAttrs_Any_Either
//
// Fills in a span structure with the given attributes.
// Handles any set of attributes via USED flags.
// Uses and updates PWL support.
//
//----------------------------------------------------------------------------
void FASTCALL FillSpanFloatAttrs_Any_Either(PATTRSET pAttr, PD3DI_RASTSPAN pSpan, PSETUPCTX pStpCtx, INT cPix) { FLOAT fPix = (FLOAT)cPix; pSpan->pSurface = pAttr->pSurface; pSpan->pZ = pAttr->pZ;
if (pStpCtx->uFlags & PRIMSF_Z_USED) { pSpan->uZ = FTOI(pAttr->fZ); }
if (pStpCtx->uFlags & PRIMSF_TEX_USED) { FLOAT fW;
if (pStpCtx->uPwlFlags & PWL_NEXT_LOD) { fW = pStpCtx->fNextW; } else if (pStpCtx->uFlags & PRIMSF_PERSP_USED) { if (FLOAT_EQZ(pAttr->fOoW)) { fW = g_fZero; } else { fW = OOW_SCALE / pAttr->fOoW; } } else { fW = g_fOne; }
pSpan->iW = FTOI(fW * W_SCALE);
if (pStpCtx->uFlags & PRIMSF_LOD_USED) { // Mipmapping is enabled so compute texture LOD.
// The span code can do linear LOD interpolation
// so that we can do piecewise-linear approximations
// instead of true per-pixel LOD. In order to make this
// work we need to compute the next LOD and a delta
// value. All of these values can be reused if this
// loop goes around so keep them available for the next
// iteration and set a flag to indicate that they've
// been computed.
if (pStpCtx->uPwlFlags & PWL_NEXT_LOD) { pSpan->iLOD = (INT16)pStpCtx->iNextLOD; } else { pSpan->iLOD = (INT16)ComputeLOD(pStpCtx->pCtx, (pAttr->fUoW1 * OO_TEX_SCALE) * fW, (pAttr->fVoW1 * OO_TEX_SCALE) * fW, fW, (pStpCtx->DAttrDX.fUoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDX.fVoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDX.fOoW * OO_OOW_SCALE), (pStpCtx->DAttrDY.fUoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDY.fVoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDY.fOoW * OO_OOW_SCALE)); }
if (pStpCtx->uFlags & PRIMSF_PERSP_USED) { pStpCtx->fNextOoW = pAttr->fOoW + pStpCtx->DAttrDX.fOoW * fPix;
if (FLOAT_EQZ(pStpCtx->fNextOoW)) { fW = g_fZero; } else { fW = OOW_SCALE / pStpCtx->fNextOoW; } } else { pStpCtx->fNextOoW = OOW_SCALE; fW = g_fOne; }
pStpCtx->fNextW = fW; pStpCtx->fNextUoW1 = pAttr->fUoW1 + pStpCtx->DAttrDX.fUoW1 * fPix; pStpCtx->fNextVoW1 = pAttr->fVoW1 + pStpCtx->DAttrDX.fVoW1 * fPix; pStpCtx->iNextLOD = ComputeLOD(pStpCtx->pCtx, (pStpCtx->fNextUoW1 * OO_TEX_SCALE) * fW, (pStpCtx->fNextVoW1 * OO_TEX_SCALE) * fW, fW, (pStpCtx->DAttrDX.fUoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDX.fVoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDX.fOoW * OO_OOW_SCALE), (pStpCtx->DAttrDY.fUoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDY.fVoW1 * OO_TEX_SCALE), (pStpCtx->DAttrDY.fOoW * OO_OOW_SCALE)); pStpCtx->uPwlFlags |= PWL_NEXT_LOD;
pSpan->iDLOD = (INT16) FTOI((FLOAT)(pStpCtx->iNextLOD - pSpan->iLOD) / fPix); } else { pSpan->iLOD = 0; pSpan->iDLOD = 0; }
pSpan->iOoW = FTOI(pAttr->fOoW);
pSpan->iUoW1 = FTOI(pAttr->fUoW1); pSpan->iVoW1 = FTOI(pAttr->fVoW1); }
if (pStpCtx->uFlags & PRIMSF_TEX2_USED) { pSpan->iUoW2 = FTOI(pAttr->fUoW2); pSpan->iVoW2 = FTOI(pAttr->fVoW2); }
if (pStpCtx->uFlags & PRIMSF_DIFF_USED) { pSpan->uB = (INT16)FTOI(pAttr->fB); pSpan->uG = (INT16)FTOI(pAttr->fG); pSpan->uR = (INT16)FTOI(pAttr->fR); pSpan->uA = (INT16)FTOI(pAttr->fA); } else if (pStpCtx->uFlags & PRIMSF_DIDX_USED) { pSpan->iIdx = FTOI(pAttr->fDIdx); pSpan->iIdxA = FTOI(pAttr->fDIdxA); }
if (pStpCtx->uFlags & PRIMSF_SPEC_USED) { pSpan->uBS = (INT16)FTOI(pAttr->fBS); pSpan->uGS = (INT16)FTOI(pAttr->fGS); pSpan->uRS = (INT16)FTOI(pAttr->fRS); }
if (pStpCtx->uFlags & PRIMSF_LOCAL_FOG_USED) { pSpan->uFog = (INT16)FTOI(pAttr->fFog); pSpan->iDFog = (INT16)(pStpCtx->iDLocalFogDX); } #ifdef PWL_FOG
else if (pStpCtx->uFlags & PRIMSF_GLOBAL_FOG_USED) { FLOAT fOoZScale;
// The span code doesn't have direct global fog support.
// It's faked by setup doing PWL approximations here
// similarly to how LOD is handled.
if (pStpCtx->pCtx->iZBitCount == 16) { fOoZScale = OO_Z16_SCALE; } else { fOoZScale = OO_Z32_SCALE; }
if (pStpCtx->uPwlFlags & PWL_NEXT_FOG) { pSpan->uFog = pStpCtx->uNextFog; } else { pSpan->uFog = ComputeTableFog(pStpCtx->pCtx->pdwRenderState, pAttr->fZ * fOoZScale); }
if ((pStpCtx->uPwlFlags & PWL_NO_NEXT_FOG) == 0) { pStpCtx->fNextZ = pAttr->fZ + pStpCtx->DAttrDX.fZ * fPix; pStpCtx->uNextFog = ComputeTableFog(pStpCtx->pCtx->pdwRenderState, pStpCtx->fNextZ * fOoZScale); pStpCtx->uPwlFlags |= PWL_NEXT_FOG;
pSpan->iDFog = FTOI((FLOAT)((INT)pStpCtx->uNextFog - (INT)pSpan->uFog) / fPix); } else { pSpan->iDFog = 0; } } #endif
}
//
// Tables of attribute handlers.
// Indexing is with the low four PRIMSF_*_USED bits.
//
// Attribute adders.
PFN_ADDATTRS g_pfnAddFloatAttrsTable[] = { (PFN_ADDATTRS)DebugBreakFn, /* 0: -2 -1 -S -D */ AddFloatAttrs_Z_Diff, /* 1: -2 -1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 2: -2 -1 +S -D */ AddFloatAttrs_Z_Diff_Spec, /* 3: -2 -1 +S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 4: -2 +1 -S -D */ AddFloatAttrs_Z_Diff_Tex1, /* 5: -2 +1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 6: -2 +1 +S -D */ AddFloatAttrs_Z_Diff_Spec_Tex1, /* 7: -2 +1 +S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 8: +2 -1 -S -D */ (PFN_ADDATTRS)DebugBreakFn, /* 9: +2 -1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* A: +2 -1 +S -D */ (PFN_ADDATTRS)DebugBreakFn, /* B: +2 -1 +S +D */ AddFloatAttrs_Z_Tex1_Tex2, /* C: +2 +1 -S -D */ (PFN_ADDATTRS)DebugBreakFn, /* D: +2 +1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* E: +2 +1 +S -D */ (PFN_ADDATTRS)DebugBreakFn, /* F: +2 +1 +S +D */ }; #ifdef STEP_FIXED
PFN_ADDATTRS g_pfnAddFixedAttrsTable[] = { (PFN_ADDATTRS)DebugBreakFn, /* 0: -2 -1 -S -D */ AddFixedAttrs_Z_Diff, /* 1: -2 -1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 2: -2 -1 +S -D */ AddFixedAttrs_Z_Diff_Spec, /* 3: -2 -1 +S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 4: -2 +1 -S -D */ AddFixedAttrs_Z_Diff_Tex1, /* 5: -2 +1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 6: -2 +1 +S -D */ AddFixedAttrs_Z_Diff_Spec_Tex1, /* 7: -2 +1 +S +D */ (PFN_ADDATTRS)DebugBreakFn, /* 8: +2 -1 -S -D */ (PFN_ADDATTRS)DebugBreakFn, /* 9: +2 -1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* A: +2 -1 +S -D */ (PFN_ADDATTRS)DebugBreakFn, /* B: +2 -1 +S +D */ AddFixedAttrs_Z_Tex1_Tex2, /* C: +2 +1 -S -D */ (PFN_ADDATTRS)DebugBreakFn, /* D: +2 +1 -S +D */ (PFN_ADDATTRS)DebugBreakFn, /* E: +2 +1 +S -D */ (PFN_ADDATTRS)DebugBreakFn, /* F: +2 +1 +S +D */ }; #endif
// Scaled attribute adders without PWL support.
PFN_ADDSCALEDATTRS g_pfnAddScaledFloatAttrsTable[] = { (PFN_ADDSCALEDATTRS)DebugBreakFn, /* 0: -2 -1 -S -D */ AddScaledFloatAttrs_Z_Diff, /* 1: -2 -1 -S +D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* 2: -2 -1 +S -D */ AddScaledFloatAttrs_Z_Diff_Spec, /* 3: -2 -1 +S +D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* 4: -2 +1 -S -D */ AddScaledFloatAttrs_Z_Diff_Tex1, /* 5: -2 +1 -S +D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* 6: -2 +1 +S -D */ AddScaledFloatAttrs_Z_Diff_Spec_Tex1, /* 7: -2 +1 +S +D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* 8: +2 -1 -S -D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* 9: +2 -1 -S +D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* A: +2 -1 +S -D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* B: +2 -1 +S +D */ AddScaledFloatAttrs_Z_Tex1_Tex2, /* C: +2 +1 -S -D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* D: +2 +1 -S +D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* E: +2 +1 +S -D */ (PFN_ADDSCALEDATTRS)DebugBreakFn, /* F: +2 +1 +S +D */ };
// RASTSPAN filling functions.
PFN_FILLSPANATTRS g_pfnFillSpanFloatAttrsTable[] = { (PFN_FILLSPANATTRS)DebugBreakFn, /* 0: -2 -1 -S -D */ FillSpanFloatAttrs_Z_Diff, /* 1: -2 -1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 2: -2 -1 +S -D */ FillSpanFloatAttrs_Z_Diff_Spec, /* 3: -2 -1 +S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 4: -2 +1 -S -D */ FillSpanFloatAttrs_Z_Diff_Tex1, /* 5: -2 +1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 6: -2 +1 +S -D */ FillSpanFloatAttrs_Z_Diff_Spec_Tex1, /* 7: -2 +1 +S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 8: +2 -1 -S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 9: +2 -1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* A: +2 -1 +S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* B: +2 -1 +S +D */ FillSpanFloatAttrs_Z_Tex1_Tex2, /* C: +2 +1 -S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* D: +2 +1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* E: +2 +1 +S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* F: +2 +1 +S +D */ }; #ifdef STEP_FIXED
PFN_FILLSPANATTRS g_pfnFillSpanFixedAttrsTable[] = { (PFN_FILLSPANATTRS)DebugBreakFn, /* 0: -2 -1 -S -D */ FillSpanFixedAttrs_Z_Diff, /* 1: -2 -1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 2: -2 -1 +S -D */ FillSpanFixedAttrs_Z_Diff_Spec, /* 3: -2 -1 +S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 4: -2 +1 -S -D */ FillSpanFixedAttrs_Z_Diff_Tex1, /* 5: -2 +1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 6: -2 +1 +S -D */ FillSpanFixedAttrs_Z_Diff_Spec_Tex1, /* 7: -2 +1 +S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 8: +2 -1 -S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* 9: +2 -1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* A: +2 -1 +S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* B: +2 -1 +S +D */ FillSpanFixedAttrs_Z_Tex1_Tex2, /* C: +2 +1 -S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* D: +2 +1 -S +D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* E: +2 +1 +S -D */ (PFN_FILLSPANATTRS)DebugBreakFn, /* F: +2 +1 +S +D */ }; #endif
// Float-to-fixed attribute converters.
#ifdef STEP_FIXED
PFN_FLOATATTRSTOFIXED g_pfnFloatAttrsToFixedTable[] = { (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* 0: -2 -1 -S -D */ FloatAttrsToFixed_Z_Diff, /* 1: -2 -1 -S +D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* 2: -2 -1 +S -D */ FloatAttrsToFixed_Z_Diff_Spec, /* 3: -2 -1 +S +D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* 4: -2 +1 -S -D */ FloatAttrsToFixed_Z_Diff_Tex1, /* 5: -2 +1 -S +D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* 6: -2 +1 +S -D */ FloatAttrsToFixed_Z_Diff_Spec_Tex1, /* 7: -2 +1 +S +D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* 8: +2 -1 -S -D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* 9: +2 -1 -S +D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* A: +2 -1 +S -D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* B: +2 -1 +S +D */ FloatAttrsToFixed_Z_Tex1_Tex2, /* C: +2 +1 -S -D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* D: +2 +1 -S +D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* E: +2 +1 +S -D */ (PFN_FLOATATTRSTOFIXED)DebugBreakFn, /* F: +2 +1 +S +D */ }; #endif
//
// Tables of ramp mode attribute handlers.
// Indexing is with PRIMSF_TEX1_USED and PRIMSF_DIDX_USED.
//
// Attribute adders.
PFN_ADDATTRS g_pfnRampAddFloatAttrsTable[] = { (PFN_ADDATTRS)DebugBreakFn, /* 0: -I -1 */ AddFloatAttrs_Z_Tex1, /* 1: -I +1 */ AddFloatAttrs_Z_DIdx, /* 2: +I -1 */ AddFloatAttrs_Z_DIdx_Tex1, /* 3: +I +1 */ };
// Scaled attribute adders without PWL support.
PFN_ADDSCALEDATTRS g_pfnRampAddScaledFloatAttrsTable[] = { (PFN_ADDSCALEDATTRS)DebugBreakFn, /* 0: -I -1 */ AddScaledFloatAttrs_Z_Tex1, /* 1: -I +1 */ AddScaledFloatAttrs_Z_DIdx, /* 2: +I -1 */ AddScaledFloatAttrs_Z_DIdx_Tex1, /* 3: +I +1 */ };
// RASTSPAN filling functions.
PFN_FILLSPANATTRS g_pfnRampFillSpanFloatAttrsTable[] = { (PFN_FILLSPANATTRS)DebugBreakFn, /* 0: -I -1 */ FillSpanFloatAttrs_Z_Tex1, /* 1: -I +1 */ FillSpanFloatAttrs_Z_DIdx, /* 2: +I -1 */ FillSpanFloatAttrs_Z_DIdx_Tex1, /* 3: +I +1 */ };
|