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.
1282 lines
43 KiB
1282 lines
43 KiB
//----------------------------------------------------------------------------
|
|
//
|
|
// rastctx.cpp
|
|
//
|
|
// Context functions + state functions.
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
#include "rampif.h"
|
|
#include "rampmat.hpp"
|
|
|
|
// 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(); \
|
|
} \
|
|
}
|
|
|
|
inline void
|
|
D3DContext::RampSetFogData(UINT32 uState, UINT32 uStateVal)
|
|
{
|
|
RLDDIRampLightingDriver *pRampdrv =
|
|
(RLDDIRampLightingDriver*)m_RastCtx.pRampDrv;
|
|
if (pRampdrv != NULL)
|
|
{
|
|
switch(uState)
|
|
{
|
|
case D3DRENDERSTATE_FOGENABLE :
|
|
pRampdrv->fog_enable = uStateVal;
|
|
break;
|
|
case D3DRENDERSTATE_FOGCOLOR :
|
|
pRampdrv->fog_color = uStateVal;
|
|
break;
|
|
case D3DRENDERSTATE_FOGTABLEMODE :
|
|
pRampdrv->driver.fog_mode = (D3DFOGMODE)uStateVal;
|
|
break;
|
|
case D3DRENDERSTATE_FOGTABLESTART :
|
|
pRampdrv->driver.fog_start = (FLOAT)uStateVal;
|
|
break;
|
|
case D3DRENDERSTATE_FOGTABLEEND :
|
|
pRampdrv->driver.fog_end = (FLOAT)uStateVal;
|
|
break;
|
|
case D3DRENDERSTATE_FOGTABLEDENSITY:
|
|
pRampdrv->driver.fog_density = (FLOAT)uStateVal;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// 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_RastCtx.uFlags |= RASTCTXFLAGS_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;
|
|
|
|
STATESET_INIT(m_renderstate_override);
|
|
|
|
// 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 RAMP, 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 = RGBRAMP_StoreLastPixelState;
|
|
m_fnPrims.pfnDp2SetRenderStates = RGBRAMP_Dp2SetRenderStates;
|
|
m_fnPrims.pfnDp2TextureStageState = RGBRAMP_Dp2TextureStageState;
|
|
m_fnPrims.pfnDp2SetViewport = RGBRAMP_Dp2SetViewport;
|
|
m_fnPrims.pfnDp2SetWRange = RGBRAMP_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;
|
|
}
|
|
|
|
inline HRESULT
|
|
D3DContext::CreateRampLightingDriver(void)
|
|
{
|
|
m_RastCtx.pRampDrv = RLDDIRampCreate(&m_RastCtx);
|
|
|
|
if (m_RastCtx.pRampDrv == NULL)
|
|
{
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
return D3D_OK;
|
|
}
|
|
}
|
|
|
|
inline void
|
|
D3DContext::DestroyRampLightingDriver(void)
|
|
{
|
|
RLDDIRampDestroy((RLDDIRampLightingDriver*)m_RastCtx.pRampDrv);
|
|
m_RastCtx.pRampDrv = NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextCreateC
|
|
//
|
|
// Calls RastContextCreate with the C bead set.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextCreateC(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
|
|
{
|
|
return RastContextCreate(pCtxData, (DWORD)D3DIBS_C);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextCreateCMMX
|
|
//
|
|
// Calls RastContextCreate with the CMMX bead set.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextCreateCMMX(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
|
|
{
|
|
return RastContextCreate(pCtxData, (DWORD)D3DIBS_CMMX);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextCreateRamp
|
|
//
|
|
// Calls RastContextCreate with the ramp bead set.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextCreateRamp(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = RastContextCreate(pCtxData, (DWORD)D3DIBS_RAMP);
|
|
|
|
if (pCtxData->ddrval != D3D_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Create a RampLightingDriver
|
|
D3DContext *pDCtx = (D3DContext *)pCtxData->dwhContext;
|
|
pCtxData->ddrval = pDCtx->CreateRampLightingDriver();
|
|
|
|
// Init prim function table for RAMP
|
|
pDCtx->InitRampFuncs();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// 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) &&
|
|
(D3DIBS_RAMP != BeadSet))
|
|
{
|
|
// need a ramp lighting driver for 8 bit palettized RGB output
|
|
pCtxData->ddrval = pDCtx->CreateRampLightingDriver();
|
|
|
|
if (pCtxData->ddrval == D3D_OK)
|
|
{
|
|
// initialize the RGB8 palette
|
|
RLDDIRampMakePaletteRGB8((RLDDIRampLightingDriver*)pCtx->pRampDrv);
|
|
|
|
// Make sure DD Palette is updated after it gets set by FindLightingRange
|
|
RLDDIRampUpdateDDPalette(pCtx);
|
|
}
|
|
}
|
|
|
|
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();
|
|
if (pCtx->pRampDrv)
|
|
{
|
|
// destroy the ramp lighting driver, if one was created
|
|
pDCtx->DestroyRampLightingDriver();
|
|
}
|
|
|
|
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 < 2; i++)
|
|
{
|
|
switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(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:
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_COLORARG1)] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDCOLORARG;
|
|
case (D3DTA_TEXTURE):
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_COLORARG2)] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDCOLORARG;
|
|
case (D3DTA_TFACTOR):
|
|
case (D3DTA_CURRENT):
|
|
case (D3DTA_DIFFUSE):
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(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:
|
|
// only validate alpha args if alpha op is not disable
|
|
switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_ALPHAARG1)] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDALPHAARG;
|
|
case (D3DTA_TEXTURE):
|
|
break;
|
|
}
|
|
|
|
switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_ALPHAARG2)] &
|
|
~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
|
|
{
|
|
default:
|
|
return D3DERR_UNSUPPORTEDALPHAARG;
|
|
case (D3DTA_TFACTOR):
|
|
case (D3DTA_CURRENT):
|
|
case (D3DTA_DIFFUSE):
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
// allow unused state to be zero'ed since this is so common
|
|
if ( !((m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(2,D3DTSS_COLOROP)] == D3DTOP_DISABLE) ||
|
|
(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(2,D3DTSS_COLOROP)] == 0)) )
|
|
{
|
|
return D3DERR_TOOMANYOPERATIONS;
|
|
}
|
|
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;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RastContextDestroyRamp
|
|
//
|
|
// Destroy a rast context.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RastContextDestroyRamp(LPD3DHAL_CONTEXTDESTROYDATA pCtxDestroyData)
|
|
{
|
|
D3DContext *pDCtx;
|
|
|
|
VALIDATE_D3DCONTEXT("RastContextDestroy", pCtxDestroyData);
|
|
|
|
pDCtx->DestroyRampLightingDriver();
|
|
|
|
delete pDCtx;
|
|
|
|
pCtxDestroyData->ddrval = D3D_OK;
|
|
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:
|
|
RampSetFogData(uState, uStateVal);
|
|
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.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESS)] =
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)] =
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)] = uStateVal;
|
|
MapTextureStage0State();
|
|
break;
|
|
case D3DRENDERSTATE_TEXTUREADDRESSU:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)] = uStateVal;
|
|
MapTextureStage0State();
|
|
break;
|
|
case D3DRENDERSTATE_TEXTUREADDRESSV:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)] = uStateVal;
|
|
MapTextureStage0State();
|
|
break;
|
|
case D3DRENDERSTATE_MIPMAPLODBIAS:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPMAPLODBIAS)] = uStateVal;
|
|
MapTextureStage0State();
|
|
break;
|
|
case D3DRENDERSTATE_BORDERCOLOR:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_BORDERCOLOR)] = uStateVal;
|
|
MapTextureStage0State();
|
|
break;
|
|
|
|
case D3DRENDERSTATE_TEXTUREMAG:
|
|
case D3DRENDERSTATE_TEXTUREMIN:
|
|
// map legacy filtering/sampling state to texture stage 0
|
|
MapLegacyTextureFilter();
|
|
// assign to current texture
|
|
MapTextureStage0State();
|
|
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.pdwRenderState[D3DHAL_TSS_OFFSET(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
|
|
MapTextureStage0State();
|
|
UpdateActiveTexStageCount();
|
|
break;
|
|
|
|
case D3DHAL_TSS_TEXTUREMAP0:
|
|
// 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 (m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] == 0)
|
|
{
|
|
m_RastCtx.pTexture[0] = NULL;
|
|
}
|
|
// don't set m_RastCtx.pTexture[1] = NULL (in case the handle is never
|
|
// sent again). cActTex will keep it from being used until pTexture[0] is
|
|
// set to something
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
if (HANDLE_TO_SPANTEX(uStateVal) == m_RastCtx.pTexture[1])
|
|
{
|
|
D3D_ERR( "Stage1 and 2 have same texture handle." );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
#endif
|
|
m_RastCtx.pTexture[0] = HANDLE_TO_SPANTEX(uStateVal);
|
|
}
|
|
|
|
// map stage 0 state to first texture
|
|
MapTextureStage0State();
|
|
UpdateActiveTexStageCount();
|
|
break;
|
|
|
|
case D3DHAL_TSS_TEXTUREMAP1:
|
|
// 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)
|
|
{
|
|
m_RastCtx.pTexture[1] = NULL;
|
|
}
|
|
else
|
|
{
|
|
// 2nd texture can only be enabled if there's an active
|
|
// 1st texture, but computation of cActTex will prevent this
|
|
// from happening
|
|
#if DBG
|
|
if (HANDLE_TO_SPANTEX(uStateVal) == m_RastCtx.pTexture[0])
|
|
{
|
|
D3D_ERR( "Stage1 and 2 have same texture handle." );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
#endif
|
|
m_RastCtx.pTexture[1] = HANDLE_TO_SPANTEX(uStateVal);
|
|
}
|
|
|
|
// map stage 1 state to second texture
|
|
MapTextureStage1State();
|
|
UpdateActiveTexStageCount();
|
|
break;
|
|
|
|
|
|
// map single set ADDRESS to both U and V controls for stages 0 & 1
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESS):
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)] = uStateVal;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)] = uStateVal;
|
|
MapTextureStage0State();
|
|
break;
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESS):
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSU)] = uStateVal;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSV)] = uStateVal;
|
|
MapTextureStage1State();
|
|
break;
|
|
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_MIPMAPLODBIAS):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_MAXMIPLEVEL):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_BORDERCOLOR):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_MAGFILTER):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER):
|
|
MapTextureStage0State();
|
|
break;
|
|
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSU):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSV):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_MIPMAPLODBIAS):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_MAXMIPLEVEL):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_BORDERCOLOR):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_MAGFILTER):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_MINFILTER):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_MIPFILTER):
|
|
MapTextureStage1State();
|
|
break;
|
|
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1):
|
|
case D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG1):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG2):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAOP):
|
|
case D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG1):
|
|
case D3DHAL_TSS_OFFSET(1,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<2; iStage++ )
|
|
{
|
|
// check for disabled stage (subsequent are thus inactive)
|
|
// also conservatively checks for incorrectly enabled stage (might be legacy)
|
|
if ( ( m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(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;
|
|
|
|
// Check for overrides
|
|
if (IS_OVERRIDE(type)) {
|
|
UINT32 override = GET_OVERRIDE(type);
|
|
if (pRenderState->dwState)
|
|
STATESET_SET(m_renderstate_override, override);
|
|
else
|
|
STATESET_CLEAR(m_renderstate_override, override);
|
|
continue;
|
|
}
|
|
|
|
if (STATESET_ISSET(m_renderstate_override, type))
|
|
continue;
|
|
|
|
// 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(D3DHAL_TSS_TEXTUREMAP0) ||
|
|
IsStateChanged(D3DHAL_TSS_TEXTUREMAP1) ||
|
|
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 < 2; 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;
|
|
|
|
if (m_RastCtx.pRampDrv)
|
|
{
|
|
pTexRampmapSave = m_RastCtx.pTexRampMap;
|
|
}
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// MapTextureStage0/1State - Maps state0/stage1 texture state to spantex object
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
D3DContext::MapTextureStage0State( void )
|
|
{
|
|
if (m_RastCtx.pTexture[0] == NULL) return;
|
|
//
|
|
// assign texture state from stage 0
|
|
//
|
|
m_RastCtx.pTexture[0]->TexAddrU = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)]);
|
|
m_RastCtx.pTexture[0]->TexAddrV = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)]);
|
|
m_RastCtx.pTexture[0]->BorderColor = (D3DCOLOR)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_BORDERCOLOR)]);
|
|
m_RastCtx.pTexture[0]->uMagFilter = (D3DTEXTUREMAGFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAGFILTER)]);
|
|
m_RastCtx.pTexture[0]->uMinFilter = (D3DTEXTUREMINFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)]);
|
|
m_RastCtx.pTexture[0]->uMipFilter = (D3DTEXTUREMIPFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)]);
|
|
m_RastCtx.pTexture[0]->cLOD =
|
|
(D3DTFP_NONE == m_RastCtx.pTexture[0]->uMipFilter)
|
|
? 0 : m_RastCtx.pTexture[0]->cLODTex;
|
|
{
|
|
m_RastCtx.pTexture[0]->fLODBias = m_RastCtx.pfRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPMAPLODBIAS)];
|
|
}
|
|
if (m_RastCtx.pTexture[0]->iMaxMipLevel != (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAXMIPLEVEL)])
|
|
{
|
|
m_RastCtx.pTexture[0]->iMaxMipLevel = (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAXMIPLEVEL)];
|
|
m_RastCtx.pTexture[0]->uFlags |= D3DI_SPANTEX_MAXMIPLEVELS_DIRTY;
|
|
}
|
|
}
|
|
void
|
|
D3DContext::MapTextureStage1State( void )
|
|
{
|
|
if (m_RastCtx.pTexture[1] == NULL) return;
|
|
//
|
|
// assign texture state from stage 0
|
|
//
|
|
m_RastCtx.pTexture[1]->TexAddrU = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSU)]);
|
|
m_RastCtx.pTexture[1]->TexAddrV = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSV)]);
|
|
m_RastCtx.pTexture[1]->BorderColor = (D3DCOLOR)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_BORDERCOLOR)]);
|
|
m_RastCtx.pTexture[1]->uMagFilter = (D3DTEXTUREMAGFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MAGFILTER)]);
|
|
m_RastCtx.pTexture[1]->uMinFilter = (D3DTEXTUREMINFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MINFILTER)]);
|
|
m_RastCtx.pTexture[1]->uMipFilter = (D3DTEXTUREMIPFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MIPFILTER)]);
|
|
m_RastCtx.pTexture[1]->cLOD =
|
|
(D3DTFP_NONE == m_RastCtx.pTexture[1]->uMipFilter)
|
|
? 0 : m_RastCtx.pTexture[1]->cLODTex;
|
|
{
|
|
m_RastCtx.pTexture[1]->fLODBias = m_RastCtx.pfRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MIPMAPLODBIAS)];
|
|
}
|
|
if (m_RastCtx.pTexture[1]->iMaxMipLevel != (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MAXMIPLEVEL)])
|
|
{
|
|
m_RastCtx.pTexture[1]->iMaxMipLevel = (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MAXMIPLEVEL)];
|
|
m_RastCtx.pTexture[1]->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.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAGFILTER)] = D3DTFG_POINT;
|
|
break;
|
|
case D3DFILTER_LINEAR:
|
|
// select based on aniso enable
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(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.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_POINT;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_NONE;
|
|
break;
|
|
case D3DFILTER_MIPNEAREST:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_POINT;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_POINT;
|
|
break;
|
|
case D3DFILTER_LINEARMIPNEAREST:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_POINT;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_LINEAR;
|
|
break;
|
|
case D3DFILTER_LINEAR:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_LINEAR;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_NONE;
|
|
break;
|
|
case D3DFILTER_MIPLINEAR:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_LINEAR;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_POINT;
|
|
break;
|
|
case D3DFILTER_LINEARMIPLINEAR:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_LINEAR;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(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.pdwRenderState[D3DHAL_TSS_OFFSET(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.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_SELECTARG1;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG1;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
|
|
break;
|
|
|
|
case D3DTBLEND_MODULATEMASK: // unsupported - do modulate
|
|
case D3DTBLEND_MODULATE:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_MODULATE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG1;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)] = D3DTA_DIFFUSE;
|
|
break;
|
|
|
|
case D3DTBLEND_MODULATEALPHA:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_MODULATE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_MODULATE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)] = D3DTA_DIFFUSE;
|
|
break;
|
|
|
|
case D3DTBLEND_DECALALPHA:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_BLENDTEXTUREALPHA;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG2;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)] = D3DTA_DIFFUSE;
|
|
break;
|
|
|
|
case D3DTBLEND_ADD:
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_ADD;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG2;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
|
|
m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(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();
|
|
}
|
|
|