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.
1076 lines
36 KiB
1076 lines
36 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// rastctx.cpp
|
|
//
|
|
// Context functions + state functions.
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
// Unlock previous texture if necessary. It's called before the texture handle
|
|
// is going to be changed.
|
|
#define CHECK_AND_UNLOCK_TEXTURE \
|
|
{ \
|
|
if (m_uFlags & D3DCONTEXT_TEXTURE_LOCKED) \
|
|
{ \
|
|
RastUnlockSpanTexture(); \
|
|
} \
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// FillContext
|
|
//
|
|
// Fill the context with the info. from the surfaces.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
D3DContext::FillContext(LPDIRECTDRAWSURFACE pDDS,
|
|
LPDIRECTDRAWSURFACE pDDSZ)
|
|
{
|
|
HRESULT hr;
|
|
|
|
LPDDRAWI_DDRAWSURFACE_LCL pLcl =
|
|
((LPDDRAWI_DDRAWSURFACE_INT)(pDDS))->lpLcl;
|
|
m_RastCtx.iSurfaceStride = DDSurf_Pitch(pLcl);
|
|
m_RastCtx.iSurfaceBitCount = DDSurf_BitDepth(pLcl);
|
|
m_RastCtx.iSurfaceStep = m_RastCtx.iSurfaceBitCount/8;
|
|
HR_RET(FindOutSurfFormat(&(DDSurf_PixFmt(pLcl)),
|
|
(D3DI_SPANTEX_FORMAT *)&(m_RastCtx.iSurfaceType)));
|
|
m_RastCtx.Clip.left = m_RastCtx.Clip.top = 0;
|
|
m_RastCtx.Clip.bottom = DDSurf_Height(pLcl);
|
|
m_RastCtx.Clip.right = DDSurf_Width(pLcl);
|
|
|
|
if (pDDSZ != NULL)
|
|
{
|
|
pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)(pDDSZ))->lpLcl;
|
|
m_RastCtx.pZBits = (PUINT8)SURFACE_MEMORY(pDDSZ);
|
|
m_RastCtx.iZStride = DDSurf_Pitch(pLcl);
|
|
m_RastCtx.iZBitCount = DDSurf_BitDepth(pLcl);
|
|
m_RastCtx.iZStep = m_RastCtx.iZBitCount/8;
|
|
}
|
|
else
|
|
{
|
|
m_RastCtx.pZBits = NULL;
|
|
m_RastCtx.iZStride = 0;
|
|
m_RastCtx.iZBitCount = 0;
|
|
m_RastCtx.iZStep = 0;
|
|
}
|
|
|
|
m_RastCtx.pDDS = pDDS;
|
|
m_RastCtx.pDDSZ = pDDSZ;
|
|
|
|
m_RastCtx.dwSize = sizeof(D3DI_RASTCTX);
|
|
|
|
// Make sure SpanInit is called at least once
|
|
SetAllStatesDirtyBits();
|
|
|
|
// Check for MsGolf AppHack
|
|
if (pLcl->lpSurfMore->lpDD_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_FORCEMODULATED)
|
|
{
|
|
m_uFlags |= D3DCONTEXT_APPHACK_MSGOLF;
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
HRESULT
|
|
D3DContext::Initialize(LPDIRECTDRAWSURFACE pDDS,
|
|
LPDIRECTDRAWSURFACE pDDSZ,
|
|
DWORD BeadSet,
|
|
DWORD devVer)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Initialize the primitive processor.
|
|
HR_RET(m_PrimProc.Initialize());
|
|
|
|
memset(&m_RastCtx, 0, sizeof(m_RastCtx));
|
|
|
|
m_uFlags = 0;
|
|
HR_RET(FillContext(pDDS, pDDSZ));
|
|
|
|
m_PrimProc.SetCtx(&m_RastCtx);
|
|
|
|
dwSize = sizeof(D3DContext);
|
|
|
|
// Initialize bead table enum
|
|
m_RastCtx.BeadSet = (D3DI_BEADSET)BeadSet;
|
|
|
|
// Init FVF data as legacy TL vertex
|
|
m_fvfData.preFVF = -1;
|
|
CheckFVF(D3DFVF_TLVERTEX);
|
|
|
|
m_RastCtx.uDevVer = devVer;
|
|
|
|
// All render and texture stage state is initialized by
|
|
// DIRECT3DDEVICEI::stateInitialize
|
|
|
|
// Init prim function table. It will be updated for, or when FVF
|
|
// control word changes or when fill mode changes.
|
|
m_fnPrims.pfnTri = RGB_TriNoPackSolid;
|
|
m_fnPrims.pfnPoint = RGB_PointNoPack;
|
|
m_fnPrims.pfnLine = RGB_LineNoPack;
|
|
// This one should be always the same.
|
|
m_fnPrims.pfnStoreLastPixelState = RGB_StoreLastPixelState;
|
|
m_fnPrims.pfnDp2SetRenderStates = RGB_Dp2SetRenderStates;
|
|
m_fnPrims.pfnDp2TextureStageState = RGB_Dp2TextureStageState;
|
|
m_fnPrims.pfnDp2SetViewport = RGB_Dp2SetViewport;
|
|
m_fnPrims.pfnDp2SetWRange = RGB_Dp2SetWRange;
|
|
|
|
// Enable MMX Fast Paths (Monolithics) if a registry key for it is not 0
|
|
m_RastCtx.dwMMXFPDisableMask[0] = 0x0; // enable MMX FP's by default
|
|
HKEY hKey = (HKEY) NULL;
|
|
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey) )
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwValue;
|
|
DWORD dwDisableMask[MMX_FP_DISABLE_MASK_NUM] = {0x0};
|
|
DWORD dwSize = 4;
|
|
|
|
// only code up looking at one mask, for now
|
|
DDASSERT(MMX_FP_DISABLE_MASK_NUM == 1);
|
|
|
|
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "MMXFPDisableMask0", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
|
|
dwType == REG_DWORD )
|
|
{
|
|
dwDisableMask[0] = dwValue;
|
|
}
|
|
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "MMX Fast Path", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
|
|
dwType == REG_DWORD)
|
|
{
|
|
if (dwValue == 0)
|
|
{
|
|
// Override MMXFPDisableMask0 and disable all MMX Fast Paths
|
|
m_RastCtx.dwMMXFPDisableMask[0] = 0xffffffff;
|
|
}
|
|
else
|
|
{
|
|
// Take all MMX paths not disabled by MMXFPDisableMask0
|
|
m_RastCtx.dwMMXFPDisableMask[0] = dwDisableMask[0];
|
|
}
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
HRESULT
|
|
D3DContext::SetViewport(LPD3DHAL_DP2VIEWPORTINFO pVpt)
|
|
{
|
|
m_RastCtx.Clip.left = pVpt->dwX;
|
|
m_RastCtx.Clip.top = pVpt->dwY;
|
|
m_RastCtx.Clip.bottom = pVpt->dwY + pVpt->dwHeight;
|
|
m_RastCtx.Clip.right = pVpt->dwX + pVpt->dwWidth;
|
|
return D3D_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextCreateC
|
|
//
|
|
// Calls RastContextCreate with the C bead set.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextCreateC(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
|
|
{
|
|
return RastContextCreate(pCtxData, (DWORD)D3DIBS_C);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextCreateMMX
|
|
//
|
|
// Calls RastContextCreate with the MMX bead set.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextCreateMMX(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
|
|
{
|
|
return RastContextCreate(pCtxData, (DWORD)D3DIBS_MMX);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextCreateMMXAsRGB
|
|
//
|
|
// Calls RastContextCreate with the MMX bead set, but remember that we
|
|
// came from RGB.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextCreateMMXAsRGB(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
|
|
{
|
|
return RastContextCreate(pCtxData, (DWORD)D3DIBS_MMXASRGB);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextCreate
|
|
//
|
|
// Creates a RASTCTX and initializes it with the info passed in.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextCreate(LPD3DHAL_CONTEXTCREATEDATA pCtxData, DWORD BeadSet)
|
|
{
|
|
DDASSERT(pCtxData != NULL);
|
|
|
|
D3DContext *pDCtx = new D3DContext;
|
|
|
|
if (pDCtx == NULL)
|
|
{
|
|
pCtxData->ddrval = DDERR_OUTOFMEMORY;
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
pCtxData->ddrval =
|
|
pDCtx->Initialize(pCtxData->lpDDS,
|
|
pCtxData->lpDDSZ,
|
|
BeadSet,
|
|
(DWORD)pCtxData->dwhContext);
|
|
|
|
pCtxData->dwhContext = (ULONG_PTR)pDCtx;
|
|
|
|
PD3DI_RASTCTX pCtx = pDCtx->GetRastCtx();
|
|
if (D3DI_SPTFMT_PALETTE8 == pCtx->iSurfaceType)
|
|
{
|
|
// 8 bit surfaces no longer supported by DX7
|
|
// AnanKan: Need to return a proer error message.
|
|
pCtxData->ddrval = DDERR_OUTOFMEMORY;
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextDestroy
|
|
//
|
|
// Destroy a rast context.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextDestroy(LPD3DHAL_CONTEXTDESTROYDATA pCtxDestroyData)
|
|
{
|
|
D3DContext *pDCtx;
|
|
|
|
VALIDATE_D3DCONTEXT("RastContextDestroy", pCtxDestroyData);
|
|
|
|
PD3DI_RASTCTX pCtx = pDCtx->GetRastCtx();
|
|
delete pDCtx;
|
|
|
|
pCtxDestroyData->ddrval = D3D_OK;
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// ValidateTextureStageState
|
|
//
|
|
// Utility function that returns an appropriate D3DERR_ if the current
|
|
// multi-texture setup can not be rendered, D3D_OK otherwise.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
D3DContext::ValidateTextureStageState(void)
|
|
{
|
|
#if DBG
|
|
if ((m_RastCtx.pTexture[0] == m_RastCtx.pTexture[1]) &&
|
|
(m_RastCtx.pTexture[0] != NULL) )
|
|
{
|
|
// except under very special circumstances, this will not work in RGB/MMX
|
|
// since we keep a lot of stage state in the D3DI_SPANTEX structure
|
|
D3D_ERR("(Rast) ValidateTextureStageState Warning, pTexture[0] == pTexture[1]");
|
|
}
|
|
#endif
|
|
for (INT i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
|
|
{
|
|
switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_COLOROP])
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDCOLOROPERATION;
|
|
case D3DTOP_DISABLE:
|
|
return D3D_OK; // don't have to validate further if the stage is disabled
|
|
case D3DTOP_SELECTARG1:
|
|
case D3DTOP_SELECTARG2:
|
|
case D3DTOP_MODULATE:
|
|
case D3DTOP_MODULATE2X:
|
|
case D3DTOP_MODULATE4X:
|
|
case D3DTOP_ADD:
|
|
case D3DTOP_ADDSIGNED:
|
|
case D3DTOP_BLENDDIFFUSEALPHA:
|
|
case D3DTOP_BLENDTEXTUREALPHA:
|
|
case D3DTOP_BLENDFACTORALPHA:
|
|
case D3DTOP_BLENDTEXTUREALPHAPM:
|
|
case D3DTOP_ADDSIGNED2X:
|
|
case D3DTOP_SUBTRACT:
|
|
case D3DTOP_ADDSMOOTH:
|
|
case D3DTOP_MODULATEALPHA_ADDCOLOR:
|
|
case D3DTOP_MODULATECOLOR_ADDALPHA:
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_COLORARG1] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDCOLORARG;
|
|
case (D3DTA_TEXTURE):
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_COLORARG2] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDCOLORARG;
|
|
case (D3DTA_TFACTOR):
|
|
case (D3DTA_CURRENT):
|
|
case (D3DTA_DIFFUSE):
|
|
case (D3DTA_SPECULAR):
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_ALPHAOP])
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDALPHAOPERATION;
|
|
case D3DTOP_DISABLE:
|
|
break;
|
|
case D3DTOP_SELECTARG1:
|
|
case D3DTOP_SELECTARG2:
|
|
case D3DTOP_MODULATE:
|
|
case D3DTOP_MODULATE2X:
|
|
case D3DTOP_MODULATE4X:
|
|
case D3DTOP_ADD:
|
|
case D3DTOP_ADDSIGNED:
|
|
case D3DTOP_BLENDDIFFUSEALPHA:
|
|
case D3DTOP_BLENDTEXTUREALPHA:
|
|
case D3DTOP_BLENDFACTORALPHA:
|
|
case D3DTOP_BLENDTEXTUREALPHAPM:
|
|
case D3DTOP_ADDSIGNED2X:
|
|
case D3DTOP_SUBTRACT:
|
|
case D3DTOP_ADDSMOOTH:
|
|
// only validate alpha args if alpha op is not disable
|
|
switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_ALPHAARG1] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDALPHAARG;
|
|
case (D3DTA_TEXTURE):
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_ALPHAARG2] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDALPHAARG;
|
|
case (D3DTA_TFACTOR):
|
|
case (D3DTA_CURRENT):
|
|
case (D3DTA_DIFFUSE):
|
|
case (D3DTA_SPECULAR):
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
return D3D_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastValidateTextureStageState
|
|
//
|
|
// Returns whether the current multitexture setup can be rendered and, if
|
|
// so, the number of passes required to render it.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastValidateTextureStageState(LPD3DHAL_VALIDATETEXTURESTAGESTATEDATA pData)
|
|
{
|
|
D3DContext *pDCtx;
|
|
|
|
VALIDATE_D3DCONTEXT("RastValidateTextureStageState", pData);
|
|
|
|
pData->dwNumPasses = 1;
|
|
|
|
pData->ddrval = pDCtx->ValidateTextureStageState();
|
|
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastSetRenderTarget
|
|
//
|
|
// Update a rast context with the info from a new render target.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastSetRenderTarget(LPD3DHAL_SETRENDERTARGETDATA pTgtData)
|
|
{
|
|
D3DContext *pDCtx;
|
|
|
|
VALIDATE_D3DCONTEXT("RastSetRenderTarget", pTgtData);
|
|
|
|
pTgtData->ddrval = pDCtx->FillContext(pTgtData->lpDDS, pTgtData->lpDDSZ);
|
|
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// SetRenderState
|
|
//
|
|
// Check to see if a state change requires an update to the D3DCTX.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
D3DContext::SetRenderState(UINT32 uState, UINT32 uStateVal)
|
|
{
|
|
// Assume d3dim has filtered out unchanged states
|
|
StateChanged(uState);
|
|
|
|
m_RastCtx.pdwRenderState[uState] = uStateVal;
|
|
|
|
switch(uState)
|
|
{
|
|
case D3DRENDERSTATE_FOGENABLE :
|
|
case D3DRENDERSTATE_FOGCOLOR :
|
|
case D3DRENDERSTATE_FOGTABLEMODE :
|
|
case D3DRENDERSTATE_FOGTABLESTART :
|
|
case D3DRENDERSTATE_FOGTABLEEND :
|
|
case D3DRENDERSTATE_FOGTABLEDENSITY:
|
|
break;
|
|
case D3DRENDERSTATE_CULLMODE:
|
|
// Set face culling sign from state.
|
|
switch(uStateVal)
|
|
{
|
|
case D3DCULL_CCW:
|
|
m_RastCtx.uCullFaceSign = 1;
|
|
break;
|
|
case D3DCULL_CW:
|
|
m_RastCtx.uCullFaceSign = 0;
|
|
break;
|
|
case D3DCULL_NONE:
|
|
m_RastCtx.uCullFaceSign = 2;
|
|
break;
|
|
}
|
|
break;
|
|
case D3DRENDERSTATE_ZENABLE:
|
|
if ( (D3DZB_FALSE != uStateVal) && (NULL == m_RastCtx.pDDSZ) )
|
|
{
|
|
DPF(0, "(ERROR) (Rast) SetRenderState: Can't set D3DRENDERSTATE_ZENABLE to %d if there is no Z Buffer", uStateVal);
|
|
m_RastCtx.pdwRenderState[uState] = D3DZB_FALSE;
|
|
}
|
|
break;
|
|
case D3DRENDERSTATE_LASTPIXEL:
|
|
// Set last-pixel flag from state.
|
|
if (uStateVal)
|
|
{
|
|
m_PrimProc.SetFlags(PPF_DRAW_LAST_LINE_PIXEL);
|
|
}
|
|
else
|
|
{
|
|
m_PrimProc.ClrFlags(PPF_DRAW_LAST_LINE_PIXEL);
|
|
}
|
|
break;
|
|
|
|
|
|
// map legacy modes with one-to-one mappings to texture stage 0
|
|
case D3DRENDERSTATE_TEXTUREADDRESS:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ADDRESS] =
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ADDRESSU] =
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ADDRESSV] = uStateVal;
|
|
MapTextureStageState(0);
|
|
break;
|
|
case D3DRENDERSTATE_TEXTUREADDRESSU:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ADDRESSU] = uStateVal;
|
|
MapTextureStageState(0);
|
|
break;
|
|
case D3DRENDERSTATE_TEXTUREADDRESSV:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ADDRESSV] = uStateVal;
|
|
MapTextureStageState(0);
|
|
break;
|
|
case D3DRENDERSTATE_MIPMAPLODBIAS:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MIPMAPLODBIAS] = uStateVal;
|
|
MapTextureStageState(0);
|
|
break;
|
|
case D3DRENDERSTATE_BORDERCOLOR:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_BORDERCOLOR] = uStateVal;
|
|
MapTextureStageState(0);
|
|
break;
|
|
|
|
case D3DRENDERSTATE_TEXTUREMAG:
|
|
case D3DRENDERSTATE_TEXTUREMIN:
|
|
// map legacy filtering/sampling state to texture stage 0
|
|
MapLegacyTextureFilter();
|
|
// assign to current texture
|
|
MapTextureStageState(0);
|
|
break;
|
|
|
|
case D3DRENDERSTATE_TEXTUREMAPBLEND:
|
|
// map legacy blending state to texture stage 0
|
|
MapLegacyTextureBlend();
|
|
break;
|
|
|
|
// map legacy WRAPU/V to per-index controls
|
|
case D3DRENDERSTATE_WRAPU:
|
|
m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
|
|
m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] |= ((uStateVal) ? D3DWRAP_U : 0);
|
|
StateChanged(D3DRENDERSTATE_WRAP0);
|
|
break;
|
|
case D3DRENDERSTATE_WRAPV:
|
|
m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
|
|
m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] |= ((uStateVal) ? D3DWRAP_V : 0);
|
|
StateChanged(D3DRENDERSTATE_WRAP0);
|
|
break;
|
|
|
|
//
|
|
// NOTE - this compututation of cActTex does not account for blend-only stages
|
|
//
|
|
case D3DRENDERSTATE_TEXTUREHANDLE:
|
|
|
|
CHECK_AND_UNLOCK_TEXTURE;
|
|
|
|
// map handle thru to stage 0
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_TEXTUREMAP] = uStateVal;
|
|
m_RastCtx.pTexture[1] = NULL;
|
|
// set up for single stage
|
|
if (uStateVal == 0)
|
|
{
|
|
m_RastCtx.pTexture[0] = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_RastCtx.pTexture[0] = HANDLE_TO_SPANTEX(uStateVal);
|
|
}
|
|
// map stage 0 state to first texture
|
|
MapTextureStageState(0);
|
|
UpdateActiveTexStageCount();
|
|
break;
|
|
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
HRESULT
|
|
D3DContext::SetTextureStageState(DWORD dwStage, DWORD dwState, DWORD uStateVal)
|
|
{
|
|
// Assume d3dim has filtered out unchanged states
|
|
StateChanged(RAST_TSS_DIRTYBIT(dwStage, dwState));
|
|
|
|
m_RastCtx.pdwTextureStageState[dwStage][dwState] = uStateVal;
|
|
switch (dwState)
|
|
{
|
|
case D3DTSS_TEXTUREMAP:
|
|
// Silently zero out legacy handle. They didn't mean it.
|
|
if (m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] != 0 &&
|
|
uStateVal != 0)
|
|
{
|
|
m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] = 0;
|
|
}
|
|
|
|
CHECK_AND_UNLOCK_TEXTURE;
|
|
|
|
if (uStateVal == 0)
|
|
{
|
|
if (dwStage == 0)
|
|
{
|
|
if (m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] == 0 )
|
|
{
|
|
m_RastCtx.pTexture[0] = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_RastCtx.pTexture[dwStage] = NULL;
|
|
}
|
|
// disables higher stages also, but don't clear pTexture[i]'s
|
|
// since they may be used later when this stage is set to non-NULL
|
|
}
|
|
else
|
|
{
|
|
// if lower stages are null, this will be noted by UpdateActiveTexStageCount
|
|
m_RastCtx.pTexture[dwStage] = HANDLE_TO_SPANTEX(uStateVal);
|
|
}
|
|
|
|
#if DBG
|
|
if (m_RastCtx.pTexture[dwStage])
|
|
{
|
|
int iTexCount = 0;
|
|
for (int i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
|
|
{
|
|
if (m_RastCtx.pTexture[dwStage] == m_RastCtx.pTexture[i])
|
|
{
|
|
iTexCount ++;
|
|
}
|
|
}
|
|
if (iTexCount > 1)
|
|
{
|
|
D3D_ERR( "Same texture handle was used more than once." );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
#endif
|
|
// map stage state to texture
|
|
MapTextureStageState(dwStage);
|
|
UpdateActiveTexStageCount();
|
|
break;
|
|
|
|
// map single set ADDRESS to both U and V controls for stages 0 & 1
|
|
case D3DTSS_ADDRESS:
|
|
m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSU] = uStateVal;
|
|
m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSV] = uStateVal;
|
|
MapTextureStageState(dwStage);
|
|
break;
|
|
case D3DTSS_ADDRESSU:
|
|
case D3DTSS_ADDRESSV:
|
|
case D3DTSS_MIPMAPLODBIAS:
|
|
case D3DTSS_MAXMIPLEVEL:
|
|
case D3DTSS_BORDERCOLOR:
|
|
case D3DTSS_MAGFILTER:
|
|
case D3DTSS_MINFILTER:
|
|
case D3DTSS_MIPFILTER:
|
|
MapTextureStageState(dwStage);
|
|
break;
|
|
case D3DTSS_COLOROP:
|
|
case D3DTSS_COLORARG1:
|
|
case D3DTSS_COLORARG2:
|
|
case D3DTSS_ALPHAOP:
|
|
case D3DTSS_ALPHAARG1:
|
|
case D3DTSS_ALPHAARG2:
|
|
// anything that effects the validity of the texture blending
|
|
// could change the number of active texture stages
|
|
UpdateActiveTexStageCount();
|
|
break;
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// UpdateActiveTexStageCount - Steps through per-stage renderstate and computes
|
|
// a count of currently active texture stages. For legacy texture, the count
|
|
// is at most one.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT D3DContext::UpdateActiveTexStageCount( void )
|
|
{
|
|
HRESULT hr;
|
|
UINT cNewActTex = 0;
|
|
|
|
// conservative but correct
|
|
if ((hr = ValidateTextureStageState()) == D3D_OK)
|
|
{
|
|
// always one active texture stage for legacy texture mode
|
|
if ( NULL != m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] )
|
|
{
|
|
cNewActTex = 1;
|
|
}
|
|
else
|
|
{
|
|
// count number of contiguous-from-zero active texture blend stages
|
|
for ( INT iStage=0; iStage<D3DHAL_TSS_MAXSTAGES; iStage++ )
|
|
{
|
|
// check for disabled stage (subsequent are thus inactive)
|
|
// also conservatively checks for incorrectly enabled stage (might be legacy)
|
|
if ( ( m_RastCtx.pdwTextureStageState[iStage][D3DTSS_COLOROP] == D3DTOP_DISABLE ) ||
|
|
( m_RastCtx.pTexture[iStage] == NULL ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// stage is active
|
|
cNewActTex ++;
|
|
}
|
|
}
|
|
}
|
|
if (m_RastCtx.cActTex != cNewActTex)
|
|
{
|
|
CHECK_AND_UNLOCK_TEXTURE;
|
|
StateChanged(D3DRENDERSTATE_TEXTUREHANDLE);
|
|
m_RastCtx.cActTex = cNewActTex;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// UpdateRenderStates
|
|
//
|
|
// Update a list of render states and notify components of state change.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT D3DContext::
|
|
UpdateRenderStates(LPDWORD puStateChange, UINT cStateChanges)
|
|
{
|
|
HRESULT hr;
|
|
INT i;
|
|
UINT32 State, StateVal;
|
|
|
|
if (cStateChanges == 0)
|
|
{
|
|
return D3D_OK;
|
|
}
|
|
|
|
// Update the D3DCTX
|
|
for (i = 0; i < (INT)cStateChanges; i++)
|
|
{
|
|
State = *puStateChange ++;
|
|
StateVal = * puStateChange++;
|
|
HR_RET(SetRenderState(State, StateVal));
|
|
}
|
|
return D3D_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// UpdateAllRenderStates
|
|
//
|
|
// Update all render states.
|
|
// It is still kept here because we probably need it in the case of fail-over.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
D3DContext::UpdateAllRenderStates(LPDWORD puStates)
|
|
{
|
|
HRESULT hr, hrSet;
|
|
INT i;
|
|
|
|
DDASSERT(puStates != NULL);
|
|
|
|
// Update D3DCTX.
|
|
// Attempt to set as many states as possible, even if there are
|
|
// errors on some. This allows context initialization to work
|
|
// even though some of the states fail due to dependencies on
|
|
// other state, such as active texture handles.
|
|
// SetRenderState failures are noted and returned eventually,
|
|
// even if everything else succeeds.
|
|
hrSet = D3D_OK;
|
|
for (i = 0; i < D3DHAL_MAX_RSTATES_AND_STAGES; i++)
|
|
{
|
|
if ((hr = SetRenderState(i, puStates[i])) != D3D_OK)
|
|
{
|
|
hrSet = hr;
|
|
}
|
|
}
|
|
|
|
return hrSet;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Dp2SetRenderStates
|
|
//
|
|
// Called by Drawprim2 to set render states..
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
D3DContext::Dp2SetRenderStates(LPD3DHAL_DP2COMMAND pCmd, LPDWORD lpdwRuntimeRStates)
|
|
{
|
|
WORD wStateCount = pCmd->wStateCount;
|
|
INT i;
|
|
HRESULT hr;
|
|
D3DHAL_DP2RENDERSTATE *pRenderState =
|
|
(D3DHAL_DP2RENDERSTATE *)(pCmd + 1);
|
|
// Flush the prim proc before any state changs
|
|
HR_RET(End(FALSE));
|
|
|
|
for (i = 0; i < (INT)wStateCount; i++, pRenderState++)
|
|
{
|
|
UINT32 type = (UINT32) pRenderState->RenderState;
|
|
|
|
// Set the runtime copy (if necessary)
|
|
if (NULL != lpdwRuntimeRStates)
|
|
{
|
|
lpdwRuntimeRStates[pRenderState->RenderState] = pRenderState->dwState;
|
|
}
|
|
|
|
// Set the state
|
|
HR_RET(SetRenderState(pRenderState->RenderState,
|
|
pRenderState->dwState));
|
|
}
|
|
|
|
hr = Begin();
|
|
return hr;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// Begin - Before rendering preparation
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
D3DContext::Begin(void)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DDASSERT((m_uFlags & D3DCONTEXT_IN_BEGIN) == 0);
|
|
|
|
// ATTENTION call this less often?
|
|
UpdateColorKeyAndPalette();
|
|
|
|
// Check for state changes
|
|
if (IsAnyStatesChanged())
|
|
{
|
|
// Check for fillmode change
|
|
if (IsStateChanged(D3DRENDERSTATE_FILLMODE))
|
|
{
|
|
UpdatePrimFunctionTbl();
|
|
}
|
|
|
|
BOOL bMaxMipLevelsDirty = FALSE;
|
|
for (INT j = 0; j < (INT)m_RastCtx.cActTex; j++)
|
|
{
|
|
PD3DI_SPANTEX pSpanTex = m_RastCtx.pTexture[j];
|
|
if (pSpanTex)
|
|
{
|
|
bMaxMipLevelsDirty = bMaxMipLevelsDirty || (pSpanTex->uFlags & D3DI_SPANTEX_MAXMIPLEVELS_DIRTY);
|
|
}
|
|
}
|
|
|
|
if (IsStateChanged(D3DRENDERSTATE_TEXTUREHANDLE) ||
|
|
IsStateChanged(RAST_TSS_DIRTYBIT(0, D3DTSS_TEXTUREMAP)) ||
|
|
IsStateChanged(RAST_TSS_DIRTYBIT(1, D3DTSS_TEXTUREMAP)) ||
|
|
bMaxMipLevelsDirty)
|
|
{
|
|
// Relock texture if texture handles have changed.
|
|
// SetRenderState should have already unlocked the texture.
|
|
if (m_uFlags & D3DCONTEXT_TEXTURE_LOCKED)
|
|
{
|
|
RastUnlockSpanTexture();
|
|
}
|
|
HR_RET(RastLockSpanTexture());
|
|
}
|
|
|
|
// Check for WRAP state change
|
|
for (int iWrap=0; iWrap<8; iWrap++)
|
|
{
|
|
D3DRENDERSTATETYPE iWrapState = (D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0+iWrap);
|
|
if (IsStateChanged(iWrapState))
|
|
{
|
|
int i;
|
|
for (i=0; i < D3DHAL_TSS_MAXSTAGES; i++)
|
|
{
|
|
if (m_fvfData.TexIdx[i] == iWrap)
|
|
{
|
|
m_RastCtx.pdwWrap[i] = m_RastCtx.pdwRenderState[iWrapState];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Notify primitive Processor of state change.
|
|
m_PrimProc.StateChanged();
|
|
|
|
// Clear state dirtybits
|
|
ClearAllStatesDirtyBits();
|
|
|
|
// Must call SpanInit AFTER texture is locked, since this
|
|
// sets various flags and fields that are needed for bead choosing
|
|
// Call SpanInit to setup the beads
|
|
HR_RET(SpanInit(&m_RastCtx));
|
|
}
|
|
|
|
// If texture is not locked yet, lock it
|
|
if (!(m_uFlags & D3DCONTEXT_TEXTURE_LOCKED))
|
|
{
|
|
HR_RET(RastLockSpanTexture());
|
|
}
|
|
|
|
// Lock rendering target.
|
|
if ((hr=LockSurface(m_RastCtx.pDDS, (LPVOID *)&(m_RastCtx.pSurfaceBits))) != D3D_OK)
|
|
{
|
|
RastUnlockSpanTexture();
|
|
return hr;
|
|
}
|
|
if (m_RastCtx.pDDSZ != NULL)
|
|
{
|
|
if ((hr=LockSurface(m_RastCtx.pDDSZ, (LPVOID *)&(m_RastCtx.pZBits))) != D3D_OK)
|
|
{
|
|
RastUnlockSpanTexture();
|
|
UnlockSurface(m_RastCtx.pDDS);
|
|
return hr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_RastCtx.pZBits = NULL;
|
|
}
|
|
|
|
// Prepare the primitive processor
|
|
m_PrimProc.Begin();
|
|
m_uFlags |= D3DCONTEXT_IN_BEGIN;
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// MapTextureStageState - Maps statestage texture state to spantex object
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
D3DContext::MapTextureStageState( DWORD dwStage )
|
|
{
|
|
if (m_RastCtx.pTexture[dwStage] == NULL) return;
|
|
//
|
|
// assign texture state from stage 0
|
|
//
|
|
m_RastCtx.pTexture[dwStage]->TexAddrU = (D3DTEXTUREADDRESS)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSU]);
|
|
m_RastCtx.pTexture[dwStage]->TexAddrV = (D3DTEXTUREADDRESS)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSV]);
|
|
m_RastCtx.pTexture[dwStage]->BorderColor = (D3DCOLOR)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_BORDERCOLOR]);
|
|
m_RastCtx.pTexture[dwStage]->uMagFilter = (D3DTEXTUREMAGFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAGFILTER]);
|
|
m_RastCtx.pTexture[dwStage]->uMinFilter = (D3DTEXTUREMINFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MINFILTER]);
|
|
m_RastCtx.pTexture[dwStage]->uMipFilter = (D3DTEXTUREMIPFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MIPFILTER]);
|
|
m_RastCtx.pTexture[dwStage]->fLODBias = m_RastCtx.pfTextureStageState[dwStage][D3DTSS_MIPMAPLODBIAS];
|
|
|
|
if (m_RastCtx.pTexture[dwStage]->iMaxMipLevel != (INT32)m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAXMIPLEVEL])
|
|
{
|
|
m_RastCtx.pTexture[dwStage]->iMaxMipLevel = (INT32)m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAXMIPLEVEL];
|
|
m_RastCtx.pTexture[dwStage]->uFlags |= D3DI_SPANTEX_MAXMIPLEVELS_DIRTY;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// MapLegacyTextureFilter -
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
D3DContext::MapLegacyTextureFilter( void )
|
|
{
|
|
// D3D legacy filter specifications are (XXXMIP)YYY where XXX is the
|
|
// mip filter and YYY is the filter used within an LOD
|
|
|
|
// map MAG filter - legacy support is point or linear (and maybe aniso)
|
|
switch ( m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREMAG] )
|
|
{
|
|
default:
|
|
case D3DFILTER_NEAREST:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MAGFILTER] = D3DTFG_POINT;
|
|
break;
|
|
case D3DFILTER_LINEAR:
|
|
// select based on aniso enable
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MAGFILTER] = D3DTFG_LINEAR;
|
|
break;
|
|
}
|
|
// map MIN and MIP filter at the same time - legacy support
|
|
// has them intermingled...
|
|
switch ( m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREMIN] )
|
|
{
|
|
case D3DFILTER_NEAREST:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MINFILTER] = D3DTFN_POINT;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MIPFILTER] = D3DTFP_NONE;
|
|
break;
|
|
case D3DFILTER_MIPNEAREST:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MINFILTER] = D3DTFN_POINT;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MIPFILTER] = D3DTFP_POINT;
|
|
break;
|
|
case D3DFILTER_LINEARMIPNEAREST:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MINFILTER] = D3DTFN_POINT;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MIPFILTER] = D3DTFP_LINEAR;
|
|
break;
|
|
case D3DFILTER_LINEAR:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MINFILTER] = D3DTFN_LINEAR;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MIPFILTER] = D3DTFP_NONE;
|
|
break;
|
|
case D3DFILTER_MIPLINEAR:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MINFILTER] = D3DTFN_LINEAR;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MIPFILTER] = D3DTFP_POINT;
|
|
break;
|
|
case D3DFILTER_LINEARMIPLINEAR:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MINFILTER] = D3DTFN_LINEAR;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_MIPFILTER] = D3DTFP_LINEAR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// MapLegacyTextureBlend - Maps legacy (pre-DX6) texture blend modes to DX6
|
|
// texture blending controls. Uses per-stage program mode (first stage only).
|
|
// This mapping is done whenever the legacy TBLEND renderstate is set, and
|
|
// does overwrite any previously set DX6 texture blending controls.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
D3DContext::MapLegacyTextureBlend( void )
|
|
{
|
|
// disable texture blend processing stage 1 (this also disables subsequent stages)
|
|
m_RastCtx.pdwTextureStageState[1][D3DTSS_COLOROP] = D3DTOP_DISABLE;
|
|
|
|
// set texture blend processing stage 0 to match legacy mode
|
|
switch ( m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND] )
|
|
{
|
|
default:
|
|
case D3DTBLEND_DECALMASK: // unsupported - do decal
|
|
case D3DTBLEND_DECAL:
|
|
case D3DTBLEND_COPY:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLOROP] = D3DTOP_SELECTARG1;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
|
|
break;
|
|
|
|
case D3DTBLEND_MODULATEMASK: // unsupported - do modulate
|
|
case D3DTBLEND_MODULATE:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLOROP] = D3DTOP_MODULATE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
|
|
break;
|
|
|
|
case D3DTBLEND_MODULATEALPHA:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLOROP] = D3DTOP_MODULATE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAOP] = D3DTOP_MODULATE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
|
|
break;
|
|
|
|
case D3DTBLEND_DECALALPHA:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLOROP] = D3DTOP_BLENDTEXTUREALPHA;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG2;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
|
|
break;
|
|
|
|
case D3DTBLEND_ADD:
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLOROP] = D3DTOP_ADD;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG2;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwTextureStageState[0][D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
|
|
break;
|
|
}
|
|
|
|
// since we change [D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP), we can go from DISABLE to
|
|
// something else, and we can need to update the TexStageCount
|
|
UpdateActiveTexStageCount();
|
|
}
|
|
|