Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1904 lines
68 KiB

//-----------------------------------------------------------------------------
//
// This file contains the span state validation function.
//
// Copyright (C) Microsoft Corporation, 1997.
//
//-----------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
include(`bead.mh')
include(`rampbead.mh')
#include "BdStr_mh.h"
#include "RastCap.h"
#include "RastColl.h"
#include "RampOld.h"
static CRastCollection g_RastCollection;
UINT16 g_uDitherTable[16] =
{
0x00, 0x80, 0x20, 0xa0,
0xc0, 0x40, 0xe0, 0x60,
0x30, 0xb0, 0x10, 0x90,
0xf0, 0x70, 0xd0, 0x50
};
//-----------------------------------------------------------------------------
//
// DoZCompareSetup
//
// Initializes arithmetic Z compare state based on the Z test function.
//
//-----------------------------------------------------------------------------
void DoZCompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
{
INT32 iXorMask;
if (bIsMMX)
{
iXorMask = -1;
}
else
{
iXorMask = 1;
}
D3DCMPFUNC ZFunc = (D3DCMPFUNC)pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC];
if (!pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE])
{
// setup ALWAYS if Z is not enabled, since we may be going into
// the test beads for other reasons (like stencil)
ZFunc = D3DCMP_ALWAYS;
}
switch (ZFunc)
{
case D3DCMP_NEVER:
pCtx->iZAndMask = 0; pCtx->iZNeg = 0; pCtx->iZXorMask = iXorMask;
break;
case D3DCMP_ALWAYS:
pCtx->iZAndMask = 0; pCtx->iZNeg = 0; pCtx->iZXorMask = 0;
break;
case D3DCMP_LESS:
pCtx->iZAndMask = ~0; pCtx->iZNeg = 0; pCtx->iZXorMask = iXorMask;
break;
case D3DCMP_GREATEREQUAL:
pCtx->iZAndMask = ~0; pCtx->iZNeg = 0; pCtx->iZXorMask = 0;
break;
case D3DCMP_EQUAL:
pCtx->iZAndMask = 0x7fffffff; pCtx->iZNeg = 1; pCtx->iZXorMask =
iXorMask;
break;
case D3DCMP_NOTEQUAL:
pCtx->iZAndMask = 0x7fffffff; pCtx->iZNeg = 1; pCtx->iZXorMask = 0;
break;
default:
case D3DCMP_LESSEQUAL:
pCtx->iZAndMask = ~0; pCtx->iZNeg = 1; pCtx->iZXorMask = iXorMask;
break;
case D3DCMP_GREATER:
pCtx->iZAndMask = ~0; pCtx->iZNeg = 1; pCtx->iZXorMask = 0;
break;
}
if (bIsMMX)
{
pCtx->iZXorMask = ~pCtx->iZXorMask;
}
}
//-----------------------------------------------------------------------------
//
// DoACompareSetup
//
// Initializes arithmetic alpha compare state based on the alpha test function.
//
//-----------------------------------------------------------------------------
void DoACompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
{
INT32 iXorMask;
if (bIsMMX)
{
iXorMask = -1;
}
else
{
iXorMask = 1;
}
switch ((D3DCMPFUNC)pCtx->pdwRenderState[D3DRENDERSTATE_ALPHAFUNC])
{
case D3DCMP_NEVER:
pCtx->iAAndMask = 0; pCtx->iANeg = 0; pCtx->iAXorMask = iXorMask;
break;
default:
case D3DCMP_ALWAYS:
pCtx->iAAndMask = 0; pCtx->iANeg = 0; pCtx->iAXorMask = 0;
break;
case D3DCMP_LESS:
pCtx->iAAndMask = ~0; pCtx->iANeg = 0; pCtx->iAXorMask = iXorMask;
break;
case D3DCMP_GREATEREQUAL:
pCtx->iAAndMask = ~0; pCtx->iANeg = 0; pCtx->iAXorMask = 0;
break;
case D3DCMP_EQUAL:
pCtx->iAAndMask = 0x7fffffff; pCtx->iANeg = 1; pCtx->iAXorMask =
iXorMask;
break;
case D3DCMP_NOTEQUAL:
pCtx->iAAndMask = 0x7fffffff; pCtx->iANeg = 1; pCtx->iAXorMask = 0;
break;
case D3DCMP_LESSEQUAL:
pCtx->iAAndMask = ~0; pCtx->iANeg = 1; pCtx->iAXorMask = iXorMask;
break;
case D3DCMP_GREATER:
pCtx->iAAndMask = ~0; pCtx->iANeg = 1; pCtx->iAXorMask = 0;
break;
}
if (bIsMMX)
{
pCtx->iAXorMask = ~pCtx->iAXorMask;
}
// iARef is an 8.8 ALPHAREF value for use by RGB and MMX.
// D3DRENDERSTATE_ALPHAREF is now an 8 bit (0xff max) value.
pCtx->iARef = pCtx->pdwRenderState[D3DRENDERSTATE_ALPHAREF] << 8;
}
//-----------------------------------------------------------------------------
//
// DoSCompareSetup
//
// Initializes arithmetic stencil compare state based on the stencil function.
//
//-----------------------------------------------------------------------------
void DoSCompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
{
INT32 iXorMask;
if (bIsMMX)
{
iXorMask = -1;
}
else
{
iXorMask = 1;
}
switch ((D3DCMPFUNC)pCtx->pdwRenderState[D3DRENDERSTATE_STENCILFUNC])
{
case D3DCMP_NEVER:
pCtx->iSAndMask = 0; pCtx->iSNeg = 0; pCtx->iSXorMask = iXorMask;
break;
default:
case D3DCMP_ALWAYS:
pCtx->iSAndMask = 0; pCtx->iSNeg = 0; pCtx->iSXorMask = 0;
break;
case D3DCMP_LESS:
pCtx->iSAndMask = ~0; pCtx->iSNeg = 0; pCtx->iSXorMask = iXorMask;
break;
case D3DCMP_GREATEREQUAL:
pCtx->iSAndMask = ~0; pCtx->iSNeg = 0; pCtx->iSXorMask = 0;
break;
case D3DCMP_EQUAL:
pCtx->iSAndMask = 0x7fffffff; pCtx->iSNeg = 1; pCtx->iSXorMask =
iXorMask;
break;
case D3DCMP_NOTEQUAL:
pCtx->iSAndMask = 0x7fffffff; pCtx->iSNeg = 1; pCtx->iSXorMask = 0;
break;
case D3DCMP_LESSEQUAL:
pCtx->iSAndMask = ~0; pCtx->iSNeg = 1; pCtx->iSXorMask = iXorMask;
break;
case D3DCMP_GREATER:
pCtx->iSAndMask = ~0; pCtx->iSNeg = 1; pCtx->iSXorMask = 0;
break;
}
if (bIsMMX)
{
pCtx->iSXorMask = ~pCtx->iSXorMask;
}
}
//-----------------------------------------------------------------------------
//
// DoTexAddrSetup
//
// Initializes arithmetic texture address state state based on the texture
// address function. iTex is the texure to setup.
//
//-----------------------------------------------------------------------------
void DoTexAddrSetup(PD3DI_RASTCTX pCtx, INT32 iTex)
{
PD3DI_SPANTEX pTex = pCtx->pTexture[iTex];
// Note that it is essential to turn on mirroring when in CLAMP/BORDER mode
// to avoid filtering artifacts at the edge of the texture
switch (pTex->TexAddrU)
{
default:
case D3DTADDRESS_WRAP:
pTex->iFlipMaskU = 0; pTex->iClampMinU = 0;
pTex->iClampMaxU = 0; pTex->iClampEnU = 0; break;
case D3DTADDRESS_MIRROR:
pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = 0;
pTex->iClampMaxU = 0; pTex->iClampEnU = 0; break;
case D3DTADDRESS_CLAMP:
pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = 0;
pTex->iClampMaxU = pTex->uMaskU; pTex->iClampEnU = -1; break;
case D3DTADDRESS_BORDER:
pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = -1;
pTex->iClampMaxU = -1; pTex->iClampEnU = -1; break;
}
switch (pTex->TexAddrV)
{
default:
case D3DTADDRESS_WRAP:
pTex->iFlipMaskV = 0; pTex->iClampMinV = 0;
pTex->iClampMaxV = 0; pTex->iClampEnV = 0; break;
case D3DTADDRESS_MIRROR:
pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = 0;
pTex->iClampMaxV = 0; pTex->iClampEnV = 0; break;
case D3DTADDRESS_CLAMP:
pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = 0;
pTex->iClampMaxV = pTex->uMaskV; pTex->iClampEnV = -1; break;
case D3DTADDRESS_BORDER:
pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = -1;
pTex->iClampMaxV = -1; pTex->iClampEnV = -1; break;
}
}
// CMMX is no longer linked in
// extern BEADTABLE g_CMMX_BeadTbl;
extern BEADTABLE g_C_BeadTbl;
#ifdef _X86_
extern BEADTABLE g_MMX_BeadTbl;
#else
BEADTABLE g_MMX_BeadTbl = g_C_BeadTbl;
#endif
extern RAMPBEADTABLE g_Ramp_BeadTbl;
HRESULT RampSpanInit(PD3DI_RASTCTX pCtx, PRAMPBEADTABLE pRBT);
extern void Ramp_InitBeadTbl(void);
#if DBG
#define RANGE_CHECK(val,max) DDASSERT(((val) >= 0) && ((val) < (max)))
#else
#define RANGE_CHECK(val,max)
#endif
#undef DPF_MODNAME
#define DPF_MODNAME "SpanInit"
//-----------------------------------------------------------------------------
//
// SpanInit
//
// Initializes derived state (function pointers and arithmetic compare values)
// based on the render state, surface type, etc.
//
//-----------------------------------------------------------------------------
HRESULT SpanInit(PD3DI_RASTCTX pCtx)
{
int iZTest,
iZFormat,
iZWrite,
iZFunc,
iZDeferred,
iStencil,
iAlphaTest,
iShadeMode,
iSpecular,
iVertexFog,
iTexture,
iTextureAddr[2],
iTextureBorder[2],
iTexturePerspective,
iTextureFilter[2],
iTextureMip[2],
iTextureLOD[2],
iTextureFormat[2],
iTextureColorKey[2],
iTextureBlend,
iTextureAlphaOverride[2],
iMono,
iAlphaBlend,
iAlphaDither[2],
iBlend,
iROP,
iSrcBlend,
iDestBlend,
iTargetPixelFormat,
iDither;
PFNRENDERSPANS pfnRenderSpans;
PFNSPANLAYER pfnTex1Addr,
pfnTex2Addr,
pfnColorBlend,
pfnColorGen;
PBEADTABLE pBeadTable;
CRastCapRecord RastCapRec;
#if DBG
if (SPIGETFLAGS(DBG_USER_FLAGS) & SPIU_BREAK_ON_SPANINIT)
{
DebugBreak();
}
#endif
// make sure this is always NULL unless it is valid
pCtx->pfnRampOld = NULL;
switch (pCtx->BeadSet)
{
#ifdef _X86_
// Uncomment these (and comment out cases below) to test MMX on legacy code
// case D3DIBS_CMMX:
// case D3DIBS_C:
case D3DIBS_MMXASRGB: // this is only different in pCtx->BeadSet for identification
case D3DIBS_MMX:
pBeadTable = &g_MMX_BeadTbl;
break;
#endif
default:
SPIDPFM((SPIM_INVALID,"Invalid BeadSet %d\n",
pCtx->BeadSet));
// fall through
case D3DIBS_CMMX: // CMMX code is no longer used, make this behave the same as C
case D3DIBS_C:
pBeadTable = &g_C_BeadTbl;
break;
case D3DIBS_RAMP:
return RampSpanInit(pCtx, &g_Ramp_BeadTbl);
break;
}
DoZCompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
DoACompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
DoSCompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
// The function pointers that point to various beads are stored in
// multi-dimensional arrays. In order to access the correct bead, we
// use numerical indices into these arrays. The indices are either
// the exact value of the renderstate used to choose the bead, or are
// values chosen by looking at the value of the renderstate.
// values needed to choose Test and AlphaTest beads
iZTest = (pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE] ||
pCtx->pdwRenderState[D3DRENDERSTATE_STENCILENABLE]) ? 1 : 0;
RastCapRec.Set_ZTest(iZTest);
switch (pCtx->iZBitCount)
{
default :
SPIDPFM((SPIM_INVALID,"Invalid Z surface bit count, iZBitCount == 0x%x\n",
pCtx->iZBitCount));
case 0 :
case 16 :
iZFormat = 0;
break;
case 32 :
iZFormat = 1;
break;
}
RastCapRec.Set_ZFormat(iZFormat);
iZWrite = pCtx->pdwRenderState[D3DRENDERSTATE_ZWRITEENABLE] ? 1 : 0;
RastCapRec.Set_ZWrite(iZWrite);
switch (pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC])
{
case D3DCMP_NEVER :
case D3DCMP_ALWAYS :
iZFunc = 0;
break;
case D3DCMP_LESS :
case D3DCMP_GREATEREQUAL :
iZFunc = 1;
break;
case D3DCMP_EQUAL :
case D3DCMP_NOTEQUAL :
iZFunc = 2;
break;
default :
SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_ZFUNC == 0x%x\n",
pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC]));
case D3DCMP_LESSEQUAL :
case D3DCMP_GREATER :
iZFunc = 3;
break;
}
if (!pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE])
{
// setup ALWAYS if Z is not enabled, since we may be going into
// the test beads for other reasons (like stencil)
iZFunc = 0;
iZWrite = 0; // do not write iterated Z, but stencil will be written if needed
}
RastCapRec.Set_ZFunc(iZFunc);
// Ignore stipple (D3DRENDERSTATE_STIPPLEENABLE), since no software rasterizers do it.
RastCapRec.Set_Stipple(0);
iAlphaTest = pCtx->pdwRenderState[D3DRENDERSTATE_ALPHATESTENABLE] ? 1 : 0;
RastCapRec.Set_AlphaTest(iAlphaTest);
iStencil = pCtx->pdwRenderState[D3DRENDERSTATE_STENCILENABLE] ? 1 : 0;
RastCapRec.Set_Stencil(iStencil);
// values needed for TestFail, TexAddr1 and ColorGen beads
switch (pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE])
{
case D3DSHADE_FLAT :
iShadeMode = 0;
break;
default :
SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_SHADEMODE == 0x%x\n",
pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE]));
case D3DSHADE_GOURAUD :
case D3DSHADE_PHONG :
iShadeMode = 1;
break;
}
RastCapRec.Set_ShadeMode(iShadeMode);
iSpecular = pCtx->pdwRenderState[D3DRENDERSTATE_SPECULARENABLE] ? 1 : 0;
RastCapRec.Set_Specular(iSpecular);
iVertexFog = pCtx->pdwRenderState[D3DRENDERSTATE_FOGENABLE] ? 1 : 0;
RastCapRec.Set_VertexFog(iVertexFog);
// are we texturing at all?
if (pCtx->cActTex == 0) {
iTexture = 0;
RastCapRec.Set_Texture(iTexture);
iTextureBlend = 0;
RastCapRec.Set_TextureBlend(iTextureBlend);
iTexturePerspective = 0;
RastCapRec.Set_TexturePersp(iTexturePerspective);
iTextureAlphaOverride[0] = 0;
RastCapRec.Set_TextureAlphaOverride(0, iTextureAlphaOverride[0]);
iTextureColorKey[0] = 0;
RastCapRec.Set_TextureColorKey(0, iTextureColorKey[0]);
if (pCtx->uDevVer >= 1)
{
// DX6, DX5 required legacy behavior
iAlphaDither[0] = pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ? 1 : 0;
}
else
{
// DX3, required legacy behavior
iAlphaDither[0] =
(pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] ? 1 : 0) ||
(pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ? 1 : 0);
}
} else {
iTexturePerspective =
pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] ? 1 : 0;
RastCapRec.Set_TexturePersp(iTexturePerspective);
if (iTexturePerspective) {
iTexture = 2;
} else {
iTexture = 1;
}
// If Multi-texture then iTexture must be incremented by two. This only effects fail cases.
if (!(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)] == D3DTOP_DISABLE))
{
iTexture += 2;
}
RastCapRec.Set_Texture(iTexture);
for (INT32 i = 0; i < (INT32)pCtx->cActTex; i++)
{
DoTexAddrSetup(pCtx, i);
// values needed to choose TexAddr1 bead, TexRead routine
// easiest to deal with border separately
if ((pCtx->pTexture[i]->TexAddrU == D3DTADDRESS_BORDER) ||
(pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_BORDER)) {
iTextureBorder[i] = 1;
} else {
iTextureBorder[i] = 0;
}
RastCapRec.Set_TextureBorder(i, iTextureBorder[i]);
switch (pCtx->pTexture[i]->TexAddrU)
{
default :
SPIDPFM((SPIM_INVALID,"Invalid texture address mode, TexAddrU == 0x%x\n",
pCtx->pTexture[i]->TexAddrU));
case D3DTADDRESS_WRAP :
if ((pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_WRAP) ||
(pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_MIRROR)) {
iTextureAddr[i] = 0;
} else {
iTextureAddr[i] = 1;
}
break;
case D3DTADDRESS_MIRROR :
if ((pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_WRAP) ||
(pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_MIRROR)) {
iTextureAddr[i] = 0;
} else {
iTextureAddr[i] = 1;
}
break;
case D3DTADDRESS_CLAMP :
iTextureAddr[i] = 1;
break;
case D3DTADDRESS_BORDER :
iTextureAddr[i] = 1;
break;
}
RastCapRec.Set_TextureAddr(i, iTextureAddr[i]);
if (i >= 1)
{
// no LOD info for second texture, just use uMagFilter
switch (pCtx->pTexture[i]->uMagFilter)
{
default :
SPIDPFM((SPIM_INVALID,"Invalid texture filter mode, uMagFilter == 0x%x\n",
pCtx->pTexture[i]->uMagFilter));
case D3DTFG_POINT :
iTextureFilter[i] = 0;
break;
case D3DTFG_LINEAR :
case D3DTFG_FLATCUBIC:
case D3DTFG_GAUSSIANCUBIC:
case D3DTFG_ANISOTROPIC:
iTextureFilter[i] = 1;
break;
}
iTextureMip[i] = 0;
iTextureLOD[i] = 0;
}
else
{
switch (pCtx->pTexture[i]->uMagFilter)
{
default :
SPIDPFM((SPIM_INVALID,"Invalid texture filter mode, uMagFilter == 0x%x\n",
pCtx->pTexture[i]->uMagFilter));
case D3DTFG_POINT :
if (pCtx->pTexture[i]->uMinFilter == D3DTFN_POINT)
{
iTextureFilter[i] = 0;
}
else
{
iTextureFilter[i] = 2;
}
break;
case D3DTFG_LINEAR :
case D3DTFG_FLATCUBIC:
case D3DTFG_GAUSSIANCUBIC:
case D3DTFG_ANISOTROPIC:
if (pCtx->pTexture[i]->uMinFilter == D3DTFN_LINEAR)
{
iTextureFilter[i] = 1;
}
else
{
iTextureFilter[i] = 2;
}
break;
}
iTextureLOD[i] = 1;
if ( (i == 0) && (pCtx->pTexture[i]->uMipFilter == D3DTFP_LINEAR) )
{
iTextureMip[i] = 1;
}
else
{
iTextureMip[i] = 0;
// only set LOD to 0 if not mip filtering AND it is NOT the maybe
// bilinear filter case
if ( (pCtx->pTexture[i]->uMipFilter == D3DTFP_NONE) && (iTextureFilter[i] != 2) )
{
iTextureLOD[i] = 0;
}
}
}
RastCapRec.Set_TextureFilter(i, iTextureFilter[i]);
RastCapRec.Set_TextureMip(i, iTextureMip[i]);
RastCapRec.Set_TextureLOD(i, iTextureLOD[i]);
// set iTextureAlphaOverride if texture doesn't have an alpha and should use
// iterated alpha
iTextureAlphaOverride[i] = 0;
RastCapRec.Set_TextureAlphaOverride(i, iTextureAlphaOverride[i]);
// values needed to chose TexRead routine
switch(pCtx->pTexture[i]->Format)
{
default :
SPIDPFM((SPIM_INVALID,"Invalid texture surface bit count, "
"Format == 0x%x\n",(DWORD) pCtx->pTexture[i]->Format));
return DDERR_INVALIDPARAMS;
case D3DI_SPTFMT_B8G8R8 :
iTextureFormat[i] = 0;
iTextureAlphaOverride[i] = 1;
break;
case D3DI_SPTFMT_B8G8R8A8 :
iTextureFormat[i] = 1;
break;
case D3DI_SPTFMT_B8G8R8X8 :
// still necessary to select texture read that sets alpha to 0xff
// for alpha dither
iTextureFormat[i] = 0;
iTextureAlphaOverride[i] = 1;
break;
case D3DI_SPTFMT_B5G6R5 :
iTextureFormat[i] = 2;
iTextureAlphaOverride[i] = 1;
break;
case D3DI_SPTFMT_B5G5R5 :
iTextureFormat[i] = 3;
iTextureAlphaOverride[i] = 1;
break;
case D3DI_SPTFMT_PALETTE4 :
if (pCtx->pTexture[i]->pPalette == NULL)
{
D3D_ERR("(Rast) NULL palette in paletted texture");
return DDERR_INVALIDPARAMS;
}
if (pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_ALPHAPALETTE)
{
iTextureFormat[i] = 11;
}
else
{
iTextureFormat[i] = 4;
iTextureAlphaOverride[i] = 1;
}
break;
case D3DI_SPTFMT_PALETTE8 :
if (pCtx->pTexture[i]->pPalette == NULL)
{
D3D_ERR("(Rast) NULL palette in paletted texture");
return DDERR_INVALIDPARAMS;
}
if (pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_ALPHAPALETTE)
{
iTextureFormat[i] = 12;
}
else
{
iTextureFormat[i] = 5;
iTextureAlphaOverride[i] = 1;
}
break;
case D3DI_SPTFMT_B5G5R5A1 :
iTextureFormat[i] = 6;
break;
case D3DI_SPTFMT_B4G4R4 :
iTextureFormat[i] = 7;
iTextureAlphaOverride[i] = 1;
break;
case D3DI_SPTFMT_B4G4R4A4 :
iTextureFormat[i] = 8;
break;
case D3DI_SPTFMT_L8 :
iTextureFormat[i] = 9;
iTextureAlphaOverride[i] = 1;
break;
case D3DI_SPTFMT_L8A8 :
iTextureFormat[i] = 10;
break;
}
RastCapRec.Set_TextureFormat(i, iTextureFormat[i]);
if (pCtx->uDevVer >= 1)
{
// DX6, DX5 required legacy behavior
iTextureColorKey[i] =
pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ?
((pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) != 0) : 0;
// DX5 required. Only alpha dither only when color keying
iAlphaDither[i] = iTextureColorKey[i];
}
else
{
// Pre-DX5 Enable ColorKey for COLORKEY OR BLENDENABLE
iTextureColorKey[i] = (pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ||
pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE]) ?
((pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) != 0) : 0;
// Alpha dither if Color Key OR Alpha Blend
iAlphaDither[i] = iTextureColorKey[i] ||
(pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] != 0);
}
RastCapRec.Set_TextureColorKey(i, iTextureColorKey[i]);
}
// choose TexBlend bead
iTextureBlend = -1;
if ( (pCtx->uDevVer <= 1) && (pCtx->uFlags & RASTCTXFLAGS_APPHACK_MSGOLF)
&& (D3DTBLEND_DECAL == pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND]) )
{
// MSGolf98 App Hack - use modulate for decal, but also make sure that alpha
// gets set to 0 on 555 rendertargets so colorkey works
iTextureBlend = 2;
}
else if ((pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)] == D3DTOP_DISABLE) &&
(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] == pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)]) &&
(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] == pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)]))
{
// might be legacy texture blend mode
if ((pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] == D3DTOP_SELECTARG1) &&
(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] == D3DTOP_SELECTARG1) &&
(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] == D3DTA_TEXTURE))
{
// copy, decal, decalmask
iTextureBlend = 1;
}
if ((pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] == D3DTOP_MODULATE) &&
(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] == D3DTOP_SELECTARG1) &&
(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] == D3DTA_TEXTURE) &&
(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] == D3DTA_DIFFUSE))
{
// modulate, modulatemask
if (iTextureAlphaOverride[0])
{
iTextureBlend = 3;
}
else
{
iTextureBlend = 2;
}
}
}
if (iTextureBlend == -1)
{
INT iCOp = 0;
INT iCArg1 = 0;
INT iCArg2 = 0;
INT iAOp = 0;
INT iAArg1 = 0;
INT iAArg2 = 0;
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid COLOROP0[0] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)]));
case D3DTOP_DISABLE: iCOp = 0; break;
case D3DTOP_SELECTARG1: iCOp = 1; break;
case D3DTOP_SELECTARG2: iCOp = 2; break;
case D3DTOP_MODULATE: iCOp = 3; break;
case D3DTOP_MODULATE2X: iCOp = 4; break;
case D3DTOP_MODULATE4X: iCOp = 5; break;
case D3DTOP_ADD: iCOp = 6; break;
case D3DTOP_ADDSIGNED: iCOp = 7; break;
case D3DTOP_BLENDDIFFUSEALPHA: iCOp = 8; break;
case D3DTOP_BLENDTEXTUREALPHA: iCOp = 9; break;
case D3DTOP_BLENDFACTORALPHA: iCOp = 10; break;
case D3DTOP_BLENDTEXTUREALPHAPM: iCOp = 11; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid COLORARG1[0] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)]));
case (D3DTA_TEXTURE):
iCArg1 = 0; break;
case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
iCArg1 = 1; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
iCArg1 = 2; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
iCArg1 = 3; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid COLORARG2[0] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)]));
case (D3DTA_DIFFUSE):
iCArg2 = 0; break;
case (D3DTA_CURRENT):
iCArg2 = 1; break;
case (D3DTA_TFACTOR):
iCArg2 = 2; break;
case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
iCArg2 = 3; break;
case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
iCArg2 = 4; break;
case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
iCArg2 = 5; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
iCArg2 = 6; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
iCArg2 = 7; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
iCArg2 = 8; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
iCArg2 = 9; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
iCArg2 = 10; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
iCArg2 = 11; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid ALPHAOP[0] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)]));
case D3DTOP_DISABLE: iAOp = 0; break;
case D3DTOP_SELECTARG1: iAOp = 1; break;
case D3DTOP_SELECTARG2: iAOp = 2; break;
case D3DTOP_MODULATE: iAOp = 3; break;
case D3DTOP_MODULATE2X: iAOp = 4; break;
case D3DTOP_MODULATE4X: iAOp = 5; break;
case D3DTOP_ADD: iAOp = 6; break;
case D3DTOP_ADDSIGNED: iAOp = 7; break;
case D3DTOP_BLENDDIFFUSEALPHA: iAOp = 8; break;
case D3DTOP_BLENDTEXTUREALPHA: iAOp = 9; break;
case D3DTOP_BLENDFACTORALPHA: iAOp = 10; break;
case D3DTOP_BLENDTEXTUREALPHAPM: iAOp = 11; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG1[0] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)]));
case (D3DTA_TEXTURE):
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
iAArg1 = 0; break;
case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
iAArg1 = 1; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG2[0] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)]));
case (D3DTA_DIFFUSE):
case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
iAArg2 = 0; break;
case (D3DTA_CURRENT):
case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
iAArg2 = 1; break;
case (D3DTA_TFACTOR):
case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
iAArg2 = 2; break;
case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
iAArg2 = 3; break;
case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
iAArg2 = 4; break;
case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
iAArg2 = 5; break;
}
pCtx->pfnTexBlendOpColor[0] = pBeadTable->pTexBlendOpColorBeads->pfnTexBlendOpColor[iCOp];
pCtx->pfnTexBlendGetColor[0] = pBeadTable->pTexBlendGetColorBeads->pfnTexBlendGetColor[iCArg2][iCArg1];
pCtx->pfnTexBlendOpAlpha[0] = pBeadTable->pTexBlendOpAlphaBeads->pfnTexBlendOpAlpha[iAOp];
pCtx->pfnTexBlendGetAlpha[0] = pBeadTable->pTexBlendGetAlphaBeads->pfnTexBlendGetAlpha[iAArg2][iAArg1];
// general TexBlend
if (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)] == D3DTOP_DISABLE)
{ \
// Tex1_Gen
iTextureBlend = 4;
}
else
{
// TexM_Gen
iTextureBlend = 5;
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid COLOROP1[1] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)]));
case D3DTOP_DISABLE: iCOp = 0; break;
case D3DTOP_SELECTARG1: iCOp = 1; break;
case D3DTOP_SELECTARG2: iCOp = 2; break;
case D3DTOP_MODULATE: iCOp = 3; break;
case D3DTOP_MODULATE2X: iCOp = 4; break;
case D3DTOP_MODULATE4X: iCOp = 5; break;
case D3DTOP_ADD: iCOp = 6; break;
case D3DTOP_ADDSIGNED: iCOp = 7; break;
case D3DTOP_BLENDDIFFUSEALPHA: iCOp = 8; break;
case D3DTOP_BLENDTEXTUREALPHA: iCOp = 9; break;
case D3DTOP_BLENDFACTORALPHA: iCOp = 10; break;
case D3DTOP_BLENDTEXTUREALPHAPM: iCOp = 11; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG1)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid COLORARG1[1] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG1)]));
case (D3DTA_TEXTURE):
iCArg1 = 0; break;
case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
iCArg1 = 1; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
iCArg1 = 2; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
iCArg1 = 3; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG2)])
{
case (D3DTA_DIFFUSE):
iCArg2 = 0; break;
default:
SPIDPFM((SPIM_INVALID,"Invalid COLORARG2[1] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG2)]));
case (D3DTA_CURRENT):
iCArg2 = 1; break;
case (D3DTA_TFACTOR):
iCArg2 = 2; break;
case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
iCArg2 = 3; break;
case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
iCArg2 = 4; break;
case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
iCArg2 = 5; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
iCArg2 = 6; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
iCArg2 = 7; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
iCArg2 = 8; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
iCArg2 = 9; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
iCArg2 = 10; break;
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
iCArg2 = 11; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAOP)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid ALPHAOP[1] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAOP)]));
case D3DTOP_DISABLE: iAOp = 0; break;
case D3DTOP_SELECTARG1: iAOp = 1; break;
case D3DTOP_SELECTARG2: iAOp = 2; break;
case D3DTOP_MODULATE: iAOp = 3; break;
case D3DTOP_MODULATE2X: iAOp = 4; break;
case D3DTOP_MODULATE4X: iAOp = 5; break;
case D3DTOP_ADD: iAOp = 6; break;
case D3DTOP_ADDSIGNED: iAOp = 7; break;
case D3DTOP_BLENDDIFFUSEALPHA: iAOp = 8; break;
case D3DTOP_BLENDTEXTUREALPHA: iAOp = 9; break;
case D3DTOP_BLENDFACTORALPHA: iAOp = 10; break;
case D3DTOP_BLENDTEXTUREALPHAPM: iAOp = 11; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG1)])
{
default:
SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG1[1] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG1)]));
case (D3DTA_TEXTURE):
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
iAArg1 = 0; break;
case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
iAArg1 = 1; break;
}
switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG2)])
{
case (D3DTA_DIFFUSE):
case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
iAArg2 = 0; break;
default:
SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG2[1] == 0x%x\n",
(DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG2)]));
case (D3DTA_CURRENT):
case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
iAArg2 = 1; break;
case (D3DTA_TFACTOR):
case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
iAArg2 = 2; break;
case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
iAArg2 = 3; break;
case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
iAArg2 = 4; break;
case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
iAArg2 = 5; break;
}
pCtx->pfnTexBlendOpColor[1] = pBeadTable->pTexBlendOpColorBeads->pfnTexBlendOpColor[iCOp];
pCtx->pfnTexBlendGetColor[1] = pBeadTable->pTexBlendGetColorBeads->pfnTexBlendGetColor[iCArg2][iCArg1];
pCtx->pfnTexBlendOpAlpha[1] = pBeadTable->pTexBlendOpAlphaBeads->pfnTexBlendOpAlpha[iAOp];
pCtx->pfnTexBlendGetAlpha[1] = pBeadTable->pTexBlendGetAlphaBeads->pfnTexBlendGetAlpha[iAArg2][iAArg1];
}
}
RastCapRec.Set_TextureBlend(iTextureBlend);
}
// Ignore mono (D3DRENDERSTATE_MONOENABLE), since no software rasterizers do anything with it.
iMono = 0;
RastCapRec.Set_Mono(iMono);
// values needed to choose ColorBlend bead
iAlphaBlend =
pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] ? 1 : 0;
RastCapRec.Set_AlphaBlend(iAlphaBlend);
if (!iAlphaBlend ||
((pCtx->pdwRenderState[D3DRENDERSTATE_SRCBLEND] == D3DBLEND_ONE) &&
(pCtx->pdwRenderState[D3DRENDERSTATE_DESTBLEND] == D3DBLEND_ZERO))) {
iBlend = 0;
} else {
iBlend = 1;
}
RastCapRec.Set_Blend(iBlend);
if (pCtx->pdwRenderState[D3DRENDERSTATE_ROP2] == R2_COPYPEN) {
iROP = 0;
} else {
iROP = 1;
}
RastCapRec.Set_ROP(iROP);
// value needed to choose DestBlend routine
switch (pCtx->pdwRenderState[D3DRENDERSTATE_DESTBLEND])
{
default :
SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_DESTBLEND == 0x%x\n",
pCtx->pdwRenderState[D3DRENDERSTATE_DESTBLEND]));
case D3DBLEND_ZERO :
iDestBlend = 0;
break;
case D3DBLEND_ONE :
iDestBlend = 1;
break;
case D3DBLEND_SRCCOLOR :
iDestBlend = 2;
break;
case D3DBLEND_INVSRCCOLOR :
iDestBlend = 3;
break;
case D3DBLEND_SRCALPHA :
iDestBlend = 4;
break;
case D3DBLEND_INVSRCALPHA :
iDestBlend = 5;
break;
case D3DBLEND_DESTALPHA :
iDestBlend = 6;
break;
case D3DBLEND_INVDESTALPHA :
iDestBlend = 7;
break;
case D3DBLEND_DESTCOLOR :
iDestBlend = 8;
break;
case D3DBLEND_INVDESTCOLOR :
iDestBlend = 9;
break;
case D3DBLEND_SRCALPHASAT :
iDestBlend = 10;
break;
}
// set iSrcBlend after iDestBlend so BOTHSRCALPHA can override iDestBlend
// value needed to choose SrcBlend routine
switch (pCtx->pdwRenderState[D3DRENDERSTATE_SRCBLEND])
{
case D3DBLEND_ZERO :
iSrcBlend = 0;
break;
default :
SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_SRCBLEND == 0x%x\n",
pCtx->pdwRenderState[D3DRENDERSTATE_SRCBLEND]));
case D3DBLEND_ONE :
iSrcBlend = 1;
break;
case D3DBLEND_SRCCOLOR :
iSrcBlend = 2;
break;
case D3DBLEND_INVSRCCOLOR :
iSrcBlend = 3;
break;
case D3DBLEND_SRCALPHA :
iSrcBlend = 4;
break;
case D3DBLEND_INVSRCALPHA :
iSrcBlend = 5;
break;
case D3DBLEND_DESTALPHA :
iSrcBlend = 6;
break;
case D3DBLEND_INVDESTALPHA :
iSrcBlend = 7;
break;
case D3DBLEND_DESTCOLOR :
iSrcBlend = 8;
break;
case D3DBLEND_INVDESTCOLOR :
iSrcBlend = 9;
break;
case D3DBLEND_SRCALPHASAT :
iSrcBlend = 10;
break;
// these are special and set both source and dest
case D3DBLEND_BOTHSRCALPHA :
iSrcBlend = 4;
iDestBlend = 5;
break;
case D3DBLEND_BOTHINVSRCALPHA :
iSrcBlend = 5;
iDestBlend = 4;
break;
}
RastCapRec.Set_SrcBlend(iSrcBlend);
RastCapRec.Set_DestBlend(iDestBlend);
// values needed to choose BufWrite bead and BufRead routine
switch (pCtx->iSurfaceType)
{
default :
SPIDPFM((SPIM_INVALID,"Invalid target surface type, iSurfaceType == 0x%x\n",
pCtx->iSurfaceType));
case RR_STYPE_B8G8R8X8:
iTargetPixelFormat = 0;
break;
case RR_STYPE_B8G8R8A8:
iTargetPixelFormat = 1;
break;
case RR_STYPE_B5G6R5:
iTargetPixelFormat = 2;
break;
case RR_STYPE_B5G5R5:
iTargetPixelFormat = 3;
break;
case RR_STYPE_B5G5R5A1:
iTargetPixelFormat = 4;
break;
case RR_STYPE_B8G8R8:
iTargetPixelFormat = 5;
break;
case RR_STYPE_PALETTE8:
iTargetPixelFormat = 6;
break;
}
RastCapRec.Set_TargetPixelFormat(iTargetPixelFormat);
iDither = pCtx->pdwRenderState[D3DRENDERSTATE_DITHERENABLE] ? 1 : 0;
RastCapRec.Set_Dither(iDither);
iZDeferred = iAlphaTest || iAlphaDither[0];
// Set optional postprocessing beads first so that their addresses
// can be referenced later.
pCtx->pfnPixelEnd = pBeadTable->pPixelEndBeads->pfnPixelEnd[0];
pCtx->pfnSpanEnd = pBeadTable->pSpanEndBeads->pfnSpanEnd[0];
// start stringing beads together, back to front order avoids a lot of
// conditional logic
#if DBG
// null out all bead ptrs
pCtx->pfnBegin = NULL;
pCtx->pfnLoopEnd = NULL;
pCtx->pfnTestPassEnd = NULL;
pCtx->pfnTestFailEnd = NULL;
pCtx->pfnTex1AddrEnd = NULL;
pCtx->pfnTexRead[0] = NULL;
pCtx->pfnTexRead[1] = NULL;
pCtx->pfnTex2AddrEnd = NULL;
pCtx->pfnTexBlendEnd = NULL;
pCtx->pfnColorGenEnd = NULL;
pCtx->pfnAlphaTestPassEnd = NULL;
pCtx->pfnAlphaTestFailEnd = NULL;
pCtx->pfnSrcBlend = NULL;
pCtx->pfnDestBlend = NULL;
pCtx->pfnBufRead = NULL;
pCtx->pfnColorBlendEnd = NULL;
pCtx->pfnPixelEnd = NULL;
pCtx->pfnSpanEnd = NULL;
#endif
// range check indices used to select BufWrite bead
RANGE_CHECK(iDither,DITHERING_NUM);
RANGE_CHECK(iTargetPixelFormat,TARGETPIXELFORMAT_NUM);
// select BufWrite bead, which can be called through pfnColorBlendEnd,
// pfnAlphaTestPassEnd, pfnColorGenEnd, pfnTexBlendEnd
pCtx->pfnTexBlendEnd =
pCtx->pfnColorGenEnd =
pCtx->pfnAlphaTestPassEnd =
pCtx->pfnColorBlendEnd = pBeadTable->pBufWriteBeads->pfnBufWrite[iDither][iTargetPixelFormat];
#if DBG
strcpy(pCtx->szBufWrite,rgszBufWrite[iDither][iTargetPixelFormat]);
#endif
// range check indices used to select ColorBlend bead
RANGE_CHECK(iROP,ROP_NUM);
RANGE_CHECK(iBlend,BLEND_NUM);
// select ColorBlend bead, which can be called through
// pfnATextEnd, pfnColorGenEnd, or pfnTexBlendEnd
if ((pfnColorBlend = pBeadTable->pColorBlendBeads->pfnColorBlend[iROP][iBlend]) == NULL) {
pCtx->pfnColorBlendEnd = NULL;
} else {
pCtx->pfnTexBlendEnd =
pCtx->pfnColorGenEnd =
pCtx->pfnAlphaTestPassEnd = pfnColorBlend;
}
#if DBG
strcpy(pCtx->szColorBlend,rgszColorBlend[iROP][iBlend]);
#endif
// range check index used to select BufRead bead
RANGE_CHECK(iTargetPixelFormat,TARGETPIXELFORMAT_NUM);
// select Buf Read routine
pCtx->pfnBufRead = pBeadTable->pBufReadBeads->pfnBufRead[iTargetPixelFormat];
#if DBG
strcpy(pCtx->szBufRead,rgszBufRead[iTargetPixelFormat]);
#endif
if (iBlend) {
// range check index used to select DestBlend bead
RANGE_CHECK(iDestBlend,DESTBLEND_NUM);
// select DestBlend routine
pCtx->pfnDestBlend = pBeadTable->pDestBlendBeads->pfnDestBlend[iDestBlend];
#if DBG
strcpy(pCtx->szDestBlend,rgszDestBlend[iDestBlend]);
#endif
// range check index used to select SrcBlend bead
RANGE_CHECK(iSrcBlend,SRCBLEND_NUM);
// select SrcBlend routine
pCtx->pfnSrcBlend = pBeadTable->pSrcBlendBeads->pfnSrcBlend[iSrcBlend];
#if DBG
strcpy(pCtx->szSrcBlend,rgszSrcBlend[iSrcBlend]);
#endif
} else {
pCtx->pfnDestBlend = NULL;
pCtx->pfnSrcBlend = NULL;
#if DBG
strcpy(pCtx->szDestBlend,"NULL");
strcpy(pCtx->szSrcBlend,"NULL");
#endif
}
// select AlphaTest/AlphaDitheringTest bead, which can be called through
// pfnColorBlendEnd, pfnColorGenEnd, or pfnTexBlendEnd
// range check indices used to select AlphaTest bead
RANGE_CHECK(iStencil,STENCIL_NUM);
RANGE_CHECK(iZFormat,ZFORMAT_NUM);
RANGE_CHECK(iZWrite,ZWRITE_NUM);
RANGE_CHECK(iAlphaDither[0],COLORKEY_NUM);
RANGE_CHECK(iAlphaTest,ALPHATEST_NUM);
if (iAlphaTest || iAlphaDither[0])
{
pCtx->pfnTexBlendEnd =
pCtx->pfnColorGenEnd =
pBeadTable->pAlphaTestBeads->pfnAlphaTest[iStencil]
[iZFormat]
[iZWrite || iStencil]
[iAlphaDither[0]]
[iAlphaTest];
// If AlphaTest fails, it goes to where the BufWrite bead ends
pCtx->pfnAlphaTestFailEnd = pCtx->pfnPixelEnd;
#if DBG
strcpy(pCtx->szAlphaTest,rgszAlphaTest[iStencil][iZFormat][iZWrite]
[iAlphaDither[0]][iAlphaTest]);
#endif
}
else
{
pCtx->pfnAlphaTestPassEnd = NULL;
pCtx->pfnAlphaTestFailEnd = NULL;
#if DBG
strcpy(pCtx->szAlphaTest, "NULL");
#endif
}
// range check indices used to select ColorGen bead
RANGE_CHECK(iMono,MONO_NUM);
RANGE_CHECK(iVertexFog,VERTEXFOG_NUM);
RANGE_CHECK(iSpecular,SPECULAR_NUM);
RANGE_CHECK(iShadeMode,SHADEMODE_NUM);
// select ColorGen bead, which can be called through pfnTexBlendEnd
if ((pfnColorGen =
pBeadTable->pColorGenBeads->pfnColorGen[iMono][iVertexFog][iSpecular][iShadeMode]) == NULL) {
pCtx->pfnColorGenEnd = NULL;
} else {
pCtx->pfnTexBlendEnd = pfnColorGen;
}
#if DBG
strcpy(pCtx->szColorGen,
rgszColorGen[iMono][iVertexFog][iSpecular][iShadeMode]);
#endif
// range check indices used to select TexBlend bead
RANGE_CHECK(iTextureBlend,TEXTUREBLEND_NUM);
// select TexBlend bead, which can be called through pfnTexAddr2End,
// pfnTexAddr1End, pfnTestPassEnd, or pfnLoopEnd
pCtx->pfnLoopEnd =
pCtx->pfnTestPassEnd =
pCtx->pfnTex1AddrEnd =
pCtx->pfnTex2AddrEnd = pBeadTable->pTexBlendBeads->pfnTexBlend[iTextureBlend];
#if DBG
strcpy(pCtx->szTexBlend,rgszTexBlend[iTextureBlend]);
#endif
if (iTexture) {
if (pCtx->cActTex >= 2)
{
// range check indices used to select TexRead bead
RANGE_CHECK(iTextureColorKey[1],COLORKEY_NUM);
RANGE_CHECK(iTextureBorder[1],TEXTUREBORDER_NUM);
RANGE_CHECK(iTextureFormat[1],TEXTUREFORMAT_NUM);
// select TexAddr2 bead, which can be called through pfnTexAddr1
// select TexRead routine
pCtx->pfnTexRead[1] =
pBeadTable->pTexReadBeads->pfnTexRead[iTextureColorKey[1]][iTextureBorder[1]][iTextureFormat[1]];
#if DBG
strcpy(pCtx->szTexRead[1],
rgszTexRead[iTextureColorKey[1]][iTextureBorder[1]][iTextureFormat[1]]);
#endif
// range check indices used to select Tex1Addr bead
RANGE_CHECK(iTextureLOD[1],TEXTURELOD_NUM);
RANGE_CHECK(iTextureFilter[1],TEXTUREFILTER_NUM);
RANGE_CHECK(iTexturePerspective,TEXTUREPERSPECTIVE_NUM);
RANGE_CHECK(iTextureAddr[1],TEXTUREADDRESS_NUM);
// select TexAddr1 bead, which can be called through pfnTestPassEnd or
// pfnLoopEnd
if ((pfnTex2Addr = (pBeadTable->pTex2AddrBeads->pfnTex2Addr[iTextureFilter[1]]
[iTexturePerspective][iTextureAddr[1]])) == NULL) {
pCtx->pfnTex2AddrEnd = NULL;
} else {
pCtx->pfnLoopEnd =
pCtx->pfnTex1AddrEnd = pfnTex2Addr;
}
#if DBG
strcpy(pCtx->szTex2Addr,rgszTex2Addr[iTextureFilter[1]]
[iTexturePerspective][iTextureAddr[1]]);
#endif
} else {
pCtx->pfnTex2AddrEnd = NULL;
pCtx->pfnTexRead[1] = NULL;
#if DBG
strcpy(pCtx->szTex2Addr,"NULL");
strcpy(pCtx->szTexRead[1],"NULL");
#endif
}
// range check indices used to select TexRead bead
RANGE_CHECK(iTextureColorKey[0],COLORKEY_NUM);
RANGE_CHECK(iTextureBorder[0],TEXTUREBORDER_NUM);
RANGE_CHECK(iTextureFormat[0],TEXTUREFORMAT_NUM);
// select TexRead routine
pCtx->pfnTexRead[0] =
pBeadTable->pTexReadBeads->pfnTexRead[iTextureColorKey[0]][iTextureBorder[0]][iTextureFormat[0]];
#if DBG
strcpy(pCtx->szTexRead[0],
rgszTexRead[iTextureColorKey[0]][iTextureBorder[0]][iTextureFormat[0]]);
#endif
// range check indices used to select Tex1Addr bead
RANGE_CHECK(iTextureLOD[0],TEXTURELOD_NUM);
RANGE_CHECK(iTextureFilter[0],TEXTUREFILTER_NUM);
RANGE_CHECK(iTexturePerspective,TEXTUREPERSPECTIVE_NUM);
RANGE_CHECK(iTextureAddr[0],TEXTUREADDRESS_NUM);
// select TexAddr1 bead, which can be called through pfnTestPassEnd or
// pfnLoopEnd
if ((pfnTex1Addr = ((iTextureMip[0]) ?
(pBeadTable->pTex1AddrMipBeads->pfnTex1AddrMip[0]) :
(pBeadTable->pTex1AddrBeads->pfnTex1Addr[iTextureLOD[0]][iTextureFilter[0]]
[iTexturePerspective][iTextureAddr[0]]))) == NULL) {
pCtx->pfnTex1AddrEnd = NULL;
} else {
pCtx->pfnLoopEnd =
pCtx->pfnTestPassEnd = pfnTex1Addr;
}
#if DBG
if (iTextureMip[0])
{
strcpy(pCtx->szTex1Addr,rgszTex1AddrMip[0]);
}
else
{
strcpy(pCtx->szTex1Addr,rgszTex1Addr[iTextureLOD[0]][iTextureFilter[0]]
[iTexturePerspective][iTextureAddr[0]]);
}
#endif
} else {
pCtx->pfnTex2AddrEnd = NULL;
pCtx->pfnTexRead[0] = NULL;
pCtx->pfnTex1AddrEnd = NULL;
#if DBG
strcpy(pCtx->szTex2Addr,"NULL");
strcpy(pCtx->szTexRead[0],"NULL");
strcpy(pCtx->szTex1Addr,"NULL");
#endif
}
// select Test bead, which can be called through pfnLoopEnd
if (iZTest) {
// range check indices used to select Test bead
RANGE_CHECK(iStencil,STENCIL_NUM);
RANGE_CHECK(iZFunc,ZFUNC_NUM);
RANGE_CHECK(iZWrite,ZWRITE_NUM);
// ATTENTION range check this
// RANGE_CHECK(iAlphaTest,ALPHATEST_NUM);
RANGE_CHECK(iZFormat,ZFORMAT_NUM);
RANGE_CHECK(iSpecular,SPECULAR_NUM);
RANGE_CHECK(iVertexFog,VERTEXFOG_NUM);
RANGE_CHECK(iTexture,TEXTURE_NUM);
RANGE_CHECK(iShadeMode,SHADEMODE_NUM);
// if alpha testing, defer Z write
pCtx->pfnLoopEnd = pBeadTable->pTestBeads->pfnTest[iStencil][iZFunc]
[iZDeferred][iZWrite][iZFormat];
// select where this bead is going to go if the test fails
pCtx->pfnTestFailEnd =
pBeadTable->pTestFailBeads->pfnTestFail[iSpecular | iVertexFog][iTexture][iShadeMode];
if (iZDeferred && iStencil)
{
// If alpha testing and stenciling, need to
// defer stencil update until after the alpha test.
//
// This is not an issue for Z, since we never want to write Z
// if the Z test fails (hence we do not care about the outcome of
// the alpha test.
pCtx->pfnTestFailEnd = pCtx->pfnTestPassEnd;
}
#if DBG
strcpy(pCtx->szTest,rgszTest[iStencil][iZFunc][iZDeferred][iZWrite][iZFormat]);
strcpy(pCtx->szTestFail,
rgszTestFail[iSpecular | iVertexFog][iTexture][iShadeMode]);
#endif
} else {
pCtx->pfnTestPassEnd = NULL;
pCtx->pfnTestFailEnd = NULL;
#if DBG
strcpy(pCtx->szTest,"NULL");
strcpy(pCtx->szTestFail,"NULL");
#endif
}
// select Loop bead
pCtx->pfnBegin = pBeadTable->pBeginBeads->pfnBegin[0];
pCtx->pfnRenderSpans = pBeadTable->pRenderSpansBeads->pfnRenderSpans[0];
#if DBG
SPIDPFM((SPIM_REPORT,"Test = %s\n",pCtx->szTest));
SPIDPFM((SPIM_REPORT,"TestFail = %s\n",pCtx->szTestFail));
SPIDPFM((SPIM_REPORT,"Tex1Addr = %s\n",pCtx->szTex1Addr));
SPIDPFM((SPIM_REPORT,"TexRead1 = %s\n",pCtx->szTexRead[0]));
SPIDPFM((SPIM_REPORT,"TexRead2 = %s\n",pCtx->szTexRead[1]));
SPIDPFM((SPIM_REPORT,"Tex2Addr = %s\n",pCtx->szTex2Addr));
SPIDPFM((SPIM_REPORT,"TexBlend = %s\n",pCtx->szTexBlend));
SPIDPFM((SPIM_REPORT,"ColorGen = %s\n",pCtx->szColorGen));
SPIDPFM((SPIM_REPORT,"ColorBlend = %s\n",pCtx->szColorBlend));
SPIDPFM((SPIM_REPORT,"SrcBlend = %s\n",pCtx->szSrcBlend));
SPIDPFM((SPIM_REPORT,"DestBlend = %s\n",pCtx->szDestBlend));
SPIDPFM((SPIM_REPORT,"BufRead = %s\n",pCtx->szBufRead));
SPIDPFM((SPIM_REPORT,"AlphaTest = %s\n",pCtx->szAlphaTest));
SPIDPFM((SPIM_REPORT,"BufWrite = %s\n",pCtx->szBufWrite));
SPIDPFM((SPIM_REPORT,"RastCap = 0x%x 0x%x 0x%x\n",
RastCapRec.GetCapDWord(0),
RastCapRec.GetCapDWord(1),
RastCapRec.GetCapDWord(2)));
#if 0
DWORD dwCheckSum = RastCapRec.GetCapDWord(0) ^ RastCapRec.GetCapDWord(1) ^ RastCapRec.GetCapDWord(2);
static DWORD dwCheckSumLast;
if (dwCheckSum != dwCheckSumLast)
{
dwCheckSumLast = dwCheckSum;
DPF(0, "Spaninit");
DPF(0, "Test = %s",pCtx->szTest);
DPF(0, "TestFail = %s",pCtx->szTestFail);
DPF(0, "Tex1Addr = %s",pCtx->szTex1Addr);
DPF(0, "TexRead1 = %s",pCtx->szTexRead[0]);
DPF(0, "TexRead2 = %s",pCtx->szTexRead[1]);
DPF(0, "Tex2Addr = %s",pCtx->szTex2Addr);
DPF(0, "TexBlend = %s",pCtx->szTexBlend);
DPF(0, "ColorGen = %s",pCtx->szColorGen);
DPF(0, "ColorBlend = %s",pCtx->szColorBlend);
DPF(0, "SrcBlend = %s",pCtx->szSrcBlend);
DPF(0, "DestBlend = %s",pCtx->szDestBlend);
DPF(0, "BufRead = %s",pCtx->szBufRead);
DPF(0, "AlphaTest = %s",pCtx->szAlphaTest);
DPF(0, "BufWrite = %s",pCtx->szBufWrite);
DPF(0, "RastCap = 0x%x 0x%x 0x%x",
RastCapRec.GetCapDWord(0),
RastCapRec.GetCapDWord(1),
RastCapRec.GetCapDWord(2));
}
#endif
#endif
// is there a monolithic rasterizer that can do exactly
// what is needed?
RASTFNREC* pfnRastFnRec;
if ((pfnRastFnRec = g_RastCollection.Search(pCtx, &RastCapRec)) != NULL)
{
// yes, then replace beaded rasterizer with monolithic
DDASSERT(pfnRastFnRec->pfnRastFunc != 0);
pCtx->pfnRenderSpans = pfnRastFnRec->pfnRastFunc;
#if DBG
// null out all the others
pCtx->pfnBegin =
pCtx->pfnLoopEnd =
pCtx->pfnTestPassEnd =
pCtx->pfnTestFailEnd =
pCtx->pfnTex1AddrEnd =
pCtx->pfnTex2AddrEnd =
pCtx->pfnTexBlendEnd =
pCtx->pfnColorGenEnd =
pCtx->pfnAlphaTestPassEnd =
pCtx->pfnAlphaTestFailEnd =
pCtx->pfnColorBlendEnd =
pCtx->pfnPixelEnd = NULL;
#endif
}
#if DBG
static RASTFNREC* pfnLastRastFnRec = (RASTFNREC*)-1;
if (pfnLastRastFnRec != pfnRastFnRec)
{
if (pfnRastFnRec)
{
D3D_INFO(1, "SpanInit: Fast path rasterizer %s chosen", pfnRastFnRec->pszRastDesc);
}
else
{
D3D_WARN(1, "SpanInit: No fast path rasterizer chosen");
}
pfnLastRastFnRec = pfnRastFnRec;
}
#endif
return S_OK;
}
//-----------------------------------------------------------------------------
//
// RampSpanInit
//
// Initializes derived state (function pointers and arithmetic compare values)
// based on the render state, surface type, etc. for Ramp. This is independent of
// and quite different from the non-ramp beads.
//
//-----------------------------------------------------------------------------
HRESULT RampSpanInit(PD3DI_RASTCTX pCtx, PRAMPBEADTABLE pBeadTable)
{
int iTargetPixelFormat,
iZTest,
iZWrite,
iDither,
iTexture,
iTrans,
iTextureCopy = 0,
iTextureMonoCopy = 0,
iTextureFormat,
iTextureColorKey,
iShadeMode;
static BOOL bInitRampBeadTbl = FALSE;
static RAMPOLDBEADS* pRampOld_BeadTbl = NULL;
static PFNRAMPOLDTRI pfnRampOldTri = NULL;
if (!bInitRampBeadTbl)
{
bInitRampBeadTbl = TRUE;
Ramp_InitBeadTbl();
#if _X86_
// also see if there are fast DX5 based ramp routines
HINSTANCE hRampOldDLL = LoadLibrary("d3dramp.dll");
if (hRampOldDLL)
{
pRampOld_BeadTbl = (RAMPOLDBEADS*) GetProcAddress(hRampOldDLL, "g_RampOld_BeadTbl");
pfnRampOldTri = (PFNRAMPOLDTRI) GetProcAddress(hRampOldDLL, "RampOldTri");
}
#endif
}
DoZCompareSetup(pCtx, FALSE);
switch (pCtx->iSurfaceType)
{
default :
SPIDPFM((SPIM_INVALID,"Invalid target surface type, "
"iSurfaceType == 0x%x\n",
pCtx->iSurfaceType));
return DDERR_INVALIDPARAMS;
case RR_STYPE_PALETTE8:
iTargetPixelFormat = 0;
break;
case RR_STYPE_B5G6R5:
case RR_STYPE_B5G5R5:
case RR_STYPE_B5G5R5A1:
iTargetPixelFormat = 1;
break;
case RR_STYPE_B8G8R8X8:
case RR_STYPE_B8G8R8A8:
case RR_STYPE_B8G8R8:
iTargetPixelFormat = 2;
break;
}
iZTest = pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE] ? 1 : 0;
iZWrite = pCtx->pdwRenderState[D3DRENDERSTATE_ZWRITEENABLE] ? 1 : 0;
iDither = pCtx->pdwRenderState[D3DRENDERSTATE_DITHERENABLE] ? 1 : 0;
// are we texturing at all?
if (pCtx->cActTex == 0)
{
iTexture = 0;
iTextureFormat = 0;
iTextureColorKey = pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE];
}
else
{
iTexture =
pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] ? 9 : 1;
// values needed to chose TexRead routine
switch(pCtx->pTexture[0]->Format)
{
case D3DI_SPTFMT_PALETTE4 :
if (pCtx->pTexture[0]->pPalette == NULL)
{
D3D_ERR("(Rast) NULL palette in paletted texture");
return DDERR_INVALIDPARAMS;
}
iTextureFormat = 0;
break;
case D3DI_SPTFMT_B5G6R5:
case D3DI_SPTFMT_B5G5R5:
case D3DI_SPTFMT_B5G5R5A1:
if (pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND]
== D3DTBLEND_COPY)
{
iTextureFormat = 2;
break;
}
default :
SPIDPFM((SPIM_INVALID,"Invalid texture surface bit count, "
"Format == 0x%x\n",(DWORD) pCtx->pTexture[0]->Format));
return DDERR_INVALIDPARAMS;
case D3DI_SPTFMT_PALETTE8 :
if (pCtx->pTexture[0]->pPalette == NULL)
{
D3D_ERR("(Rast) NULL palette in paletted texture");
return DDERR_INVALIDPARAMS;
}
iTextureFormat = 1;
break;
}
iTexture += iTextureFormat;
if ((pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ||
pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE]) &&
((pCtx->pTexture[0]->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) != 0))
{
iTextureColorKey = 1;
iTexture += 2;
}
else
{
iTextureColorKey = 0;
}
if (pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND] ==
D3DTBLEND_COPY)
{
iTextureCopy = 1;
if ( (D3DI_SPTFMT_PALETTE4 == pCtx->pTexture[0]->Format) ||
(D3DI_SPTFMT_PALETTE8 == pCtx->pTexture[0]->Format) )
{
iTextureMonoCopy = 1;
}
else
{
iTextureMonoCopy = 2;
}
iTexture += 4;
}
}
iTrans = pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] ||
iTextureColorKey;
switch (pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE])
{
case D3DSHADE_FLAT :
iShadeMode = 0;
break;
default :
SPIDPFM((SPIM_INVALID,"Invalid renderstate value, "
"D3DRENDERSTATE_SHADEMODE == 0x%x\n",
pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE]));
case D3DSHADE_GOURAUD :
case D3DSHADE_PHONG :
iShadeMode = 1;
break;
}
#if DBG
static PFNRAMPOLD pfnRampOldOld = NULL;
#endif
// see if we can use an old DX5 ramp assembly routine
if ( (pRampOld_BeadTbl) &&
(iTargetPixelFormat <= 1) && (iDither == 0) &&
((iTexture == 0) || ((iTextureFormat == 1) && (iTextureCopy == 0))) )
{
int iRampOldTexture = 0;
if (iTexture)
{
if (iTexture >= 9)
{
iRampOldTexture = 2;
}
else
{
iRampOldTexture = 1;
}
}
int iRampOldTrans = iTrans;
if (iRampOldTexture)
{
iRampOldTrans = iTextureColorKey;
}
pCtx->pfnRampOld = pRampOld_BeadTbl->pfnRampOld[iTargetPixelFormat][iZTest][iShadeMode][iRampOldTexture][iRampOldTrans];
if (pCtx->pfnRampOld)
{
pCtx->pfnRampOldTri = pfnRampOldTri;
}
}
#if DBG
if ((pfnRampOldOld == NULL) && (pCtx->pfnRampOld != NULL))
{
D3D_INFO(1, "Starting to use DX5 Ramp routines.");
pfnRampOldOld = pCtx->pfnRampOld;
}
if ((pfnRampOldOld != NULL) && (pCtx->pfnRampOld == NULL))
{
D3D_INFO(1, "Starting to use DX6 Ramp routines.");
// Uncomment this to see why DX5 rasterizer was not chosen
//#define WHY_IS_RAMP_SLOW_DEBUG 1
//
#if WHY_IS_RAMP_SLOW_DEBUG
D3D_INFO(1, "Not using DX5 Ramp routines because:");
D3D_INFO(1, " pRampOld_BeadTbl 0x%x, iTargetPixelFormat %d, iDither %d",
pRampOld_BeadTbl, iTargetPixelFormat, iDither);
D3D_INFO(1, " iTexture %d, iTextureFormat %d, iTextureCopy %d",
iTexture, iTextureFormat, iTextureCopy);
D3D_INFO(1, " pCtx->pfnRampOld 0x%x, iZTest %d, iShadeMode %d, iTrans %d",
pCtx->pfnRampOld, iZTest, iShadeMode, iTrans);
#endif
pfnRampOldOld = pCtx->pfnRampOld;
}
#endif
// Select TexRead routine.
pCtx->pfnTexRead[0] =
pBeadTable->pTexReadBeads->pfnTexRead[iTextureCopy][iTextureColorKey]
[iTextureFormat];
// Select Mono routine.
pCtx->pfnLoopEnd = pBeadTable->pMonoBeads->pfnMono[iTextureMonoCopy];
// Select Begin routine.
pCtx->pfnBegin = pBeadTable->pBeginBeads->pfnBegin[0];
// Select RenderSpans routine.
// Specialized beads can only be used when:
// Z compare is less-equal.
// Target surface is 8 or 16 bit.
// When in COPY mode, target surface is 8.
if ((iZTest &&
pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC] != D3DCMP_LESSEQUAL) ||
iTargetPixelFormat > 1 ||
iTextureMonoCopy > 1)
{
pCtx->pfnRenderSpans = pBeadTable->pfnRenderSpansAny;
}
else
{
pCtx->pfnRenderSpans = pBeadTable->pRenderSpansBeads->pfnRenderSpans
[iTexture][iShadeMode][iTrans][iDither][iZWrite][iZTest]
[iTargetPixelFormat];
}
#define DBG_RAMPCHOICE
// #define DBG_RAMPCHOICE_ALL
#ifdef DBG_RAMPCHOICE
#ifndef DBG_RAMPCHOICE_ALL
static BOOL bShowedChoice = FALSE;
#endif
char msg[80];
static UINT32 iOldRampRsIndex = 0xffffffff;
UINT32 iRampRsIndex;
iRampRsIndex =
iTargetPixelFormat +
iZTest * RAMPFORMAT_NUM +
iZWrite * (RAMPZTEST_NUM * RAMPFORMAT_NUM) +
iDither * (RAMPZWRITE_NUM * RAMPZTEST_NUM * RAMPFORMAT_NUM) +
iTrans * (RAMPDITHER_NUM * RAMPZWRITE_NUM * RAMPZTEST_NUM *
RAMPFORMAT_NUM) +
iShadeMode * (RAMPTRANS_NUM * RAMPDITHER_NUM * RAMPZWRITE_NUM *
RAMPZTEST_NUM * RAMPFORMAT_NUM) +
iTexture * (RAMPSHADEMODE_NUM * RAMPTRANS_NUM * RAMPDITHER_NUM *
RAMPZWRITE_NUM * RAMPZTEST_NUM * RAMPFORMAT_NUM);
#ifndef DBG_RAMPCHOICE_ALL
if (!bShowedChoice)
#endif
{
if (iRampRsIndex != iOldRampRsIndex)
{
if (pCtx->pfnRenderSpans == pBeadTable->pfnRenderSpansAny)
{
OutputDebugStringA("!! GENERIC RAMP !!: ");
#ifndef DBG_RAMPCHOICE_ALL
bShowedChoice = TRUE;
#else
}
#endif
sprintf(msg, "Ramp %d:%d:%d:%d:%d:%d:%d = %d\n",
iTexture, iShadeMode, iTrans, iDither, iZWrite, iZTest,
iTargetPixelFormat, iRampRsIndex);
OutputDebugStringA(msg);
iOldRampRsIndex = iRampRsIndex;
#ifndef DBG_RAMPCHOICE_ALL
}
#endif
}
}
#endif
return S_OK;
}