windows-nt/Source/XPSP1/NT/multimedia/directx/dxg/ref8/drv/primfns.cpp
2020-09-26 16:20:57 +08:00

2820 lines
84 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// primfns.cpp
//
// Copyright (C) Microsoft Corporation, 1998.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.cpp"
#pragma hdrstop
//----------------------------------------------------------------------------
//
// Wrap functions
//
//----------------------------------------------------------------------------
HRESULT WrapDp2SetViewport( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetViewport(pCmd);
}
HRESULT WrapDp2SetWRange ( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetWRange(pCmd);
}
HRESULT WrapDp2SetZRange ( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetZRange(pCmd);
}
HRESULT WrapDp2SetRenderStates( RefDev *pRefDev,
DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd,
LPDWORD lpdwRuntimeRStates )
{
return pRefDev->Dp2SetRenderStates(dwFvf, pCmd, lpdwRuntimeRStates);
}
HRESULT WrapDp2SetTextureStageState( RefDev *pRefDev, DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetTextureStageState(dwFvf, pCmd);
}
HRESULT WrapDp2SetMaterial ( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetMaterial(pCmd);
}
HRESULT WrapDp2SetLight( RefDev *pRefDev,
LPD3DHAL_DP2COMMAND pCmd,
LPDWORD pdwStride )
{
return pRefDev->Dp2SetLight(pCmd, pdwStride);
}
HRESULT WrapDp2CreateLight ( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2CreateLight(pCmd);
}
HRESULT WrapDp2SetTransform( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetTransform(pCmd);
}
HRESULT WrapDp2MultiplyTransform( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2MultiplyTransform(pCmd);
}
HRESULT WrapDp2SetExtention( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetExtention(pCmd);
}
HRESULT WrapDp2SetClipPlane( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetClipPlane(pCmd);
}
HRESULT
WrapDp2SetVertexShader( RefDev *pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetVertexShader( pCmd );
}
HRESULT
WrapDp2SetVertexShaderConsts( RefDev *pRefDev,
DWORD StartReg, DWORD dwCount, LPDWORD pData )
{
return pRefDev->Dp2SetVertexShaderConsts( StartReg, dwCount, pData );
}
HRESULT
WrapDp2SetPixelShader( RefDev *pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetPixelShader( pCmd );
}
HRESULT
WrapDp2SetPixelShaderConsts( RefDev *pRefDev,
DWORD StartReg, DWORD dwCount, LPDWORD pData )
{
return pRefDev->Dp2SetPixelShaderConsts( StartReg, dwCount, pData );
}
HRESULT
WrapDp2SetStreamSource( RefDev *pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetStreamSource( pCmd );
}
HRESULT
WrapDp2SetIndices( RefDev *pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2SetIndices( pCmd );
}
HRESULT WrapDp2RecViewport( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecViewport(pCmd);
}
HRESULT WrapDp2RecWRange ( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecWRange(pCmd);
}
HRESULT WrapDp2RecZRange ( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecZRange(pCmd);
}
HRESULT WrapDp2RecRenderStates( RefDev *pRefDev,
DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd,
LPDWORD lpdwRuntimeRStates )
{
return pRefDev->Dp2RecRenderStates(dwFvf, pCmd, lpdwRuntimeRStates);
}
HRESULT WrapDp2RecTextureStageState( RefDev *pRefDev, DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecTextureStageState(dwFvf, pCmd);
}
HRESULT WrapDp2RecMaterial ( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecMaterial(pCmd);
}
HRESULT WrapDp2RecSetLight ( RefDev *pRefDev,
LPD3DHAL_DP2COMMAND pCmd,
LPDWORD pdwStride)
{
return pRefDev->Dp2RecSetLight(pCmd, pdwStride);
}
HRESULT WrapDp2RecCreateLight( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecCreateLight(pCmd);
}
HRESULT WrapDp2RecTransform( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecTransform(pCmd);
}
HRESULT WrapDp2RecExtention( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecExtention(pCmd);
}
HRESULT WrapDp2RecClipPlane( RefDev *pRefDev, LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecClipPlane(pCmd);
}
HRESULT
WrapDp2RecSetVertexShader( RefDev* pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecSetVertexShader( pCmd );
}
HRESULT
WrapDp2RecSetVertexShaderConsts( RefDev* pRefDev,
DWORD StartReg, DWORD dwCount, LPDWORD pData )
{
return pRefDev->Dp2RecSetVertexShaderConsts( StartReg, dwCount, pData );
}
HRESULT
WrapDp2RecSetPixelShader( RefDev* pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecSetPixelShader( pCmd );
}
HRESULT
WrapDp2RecSetPixelShaderConsts( RefDev* pRefDev,
DWORD StartReg, DWORD dwCount, LPDWORD pData )
{
return pRefDev->Dp2RecSetPixelShaderConsts( StartReg, dwCount, pData );
}
HRESULT
WrapDp2RecSetStreamSource( RefDev* pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecSetStreamSource( pCmd );
}
HRESULT
WrapDp2RecSetIndices( RefDev* pRefDev,
LPD3DHAL_DP2COMMAND pCmd )
{
return pRefDev->Dp2RecSetIndices( pCmd );
}
static RD_STATESETFUNCTIONTBL StateRecFunctions =
{
sizeof(RD_STATESETFUNCTIONTBL),
WrapDp2RecRenderStates,
WrapDp2RecTextureStageState,
WrapDp2RecViewport,
WrapDp2RecWRange,
WrapDp2RecMaterial,
WrapDp2RecZRange,
WrapDp2RecSetLight,
WrapDp2RecCreateLight,
WrapDp2RecTransform,
WrapDp2RecExtention,
WrapDp2RecClipPlane,
WrapDp2RecSetVertexShader,
WrapDp2RecSetVertexShaderConsts,
WrapDp2RecSetPixelShader,
WrapDp2RecSetPixelShaderConsts,
WrapDp2RecSetStreamSource,
WrapDp2RecSetIndices
};
static RD_STATESETFUNCTIONTBL StateSetFunctions =
{
sizeof(RD_STATESETFUNCTIONTBL),
WrapDp2SetRenderStates,
WrapDp2SetTextureStageState,
WrapDp2SetViewport,
WrapDp2SetWRange,
WrapDp2SetMaterial,
WrapDp2SetZRange,
WrapDp2SetLight,
WrapDp2CreateLight,
WrapDp2SetTransform,
WrapDp2SetExtention,
WrapDp2SetClipPlane,
WrapDp2SetVertexShader,
WrapDp2SetVertexShaderConsts,
WrapDp2SetPixelShader,
WrapDp2SetPixelShaderConsts,
WrapDp2SetStreamSource,
WrapDp2SetIndices,
WrapDp2MultiplyTransform
};
//----------------------------------------------------------------------------
//
// RefDev methods
//
//----------------------------------------------------------------------------
void
RefDev::StoreLastPixelState(BOOL bStore)
{
if( bStore )
{
m_LastState = GetRS()[D3DRENDERSTATE_LASTPIXEL];
SetRenderState(D3DRENDERSTATE_LASTPIXEL, 0);
}
else
{
SetRenderState(D3DRENDERSTATE_LASTPIXEL, m_LastState);
}
}
void
RefDev::SetRecStateFunctions(void)
{
pStateSetFuncTbl = &StateRecFunctions;
}
void
RefDev::SetSetStateFunctions(void)
{
pStateSetFuncTbl = &StateSetFunctions;
}
HRESULT
RefDev::Dp2SetRenderStates(DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd,
LPDWORD lpdwRuntimeRStates )
{
WORD wStateCount = pCmd->wStateCount;
INT i;
HRESULT hr = D3D_OK;
D3DHAL_DP2RENDERSTATE *pRenderState =
(D3DHAL_DP2RENDERSTATE *)(pCmd + 1);
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
SetRenderState(pRenderState->RenderState, pRenderState->dwState);
}
return hr;
}
HRESULT
RefDev::Dp2SetTextureStageState( DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd )
{
WORD wStateCount = pCmd->wStateCount;
INT i;
HRESULT hr = D3D_OK;
D3DHAL_DP2TEXTURESTAGESTATE *pTexStageState =
(D3DHAL_DP2TEXTURESTAGESTATE *)(pCmd + 1);
for (i = 0; i < (INT)wStateCount; i++, pTexStageState++)
{
SetTextureStageState( pTexStageState->wStage, pTexStageState->TSState,
pTexStageState->dwValue );
}
return hr;
}
HRESULT
RefDev::Dp2SetViewport(LPD3DHAL_DP2COMMAND pCmd)
{
LPD3DHAL_DP2VIEWPORTINFO pVpt;
// Keep only the last viewport notification
pVpt = (D3DHAL_DP2VIEWPORTINFO *)(pCmd + 1) + (pCmd->wStateCount - 1);
// Update T&L viewport state
D3DVIEWPORT7& vp = m_Clipper.m_Viewport;
vp.dwX = pVpt->dwX;
vp.dwY = pVpt->dwY;
vp.dwWidth = pVpt->dwWidth;
vp.dwHeight = pVpt->dwHeight;
m_Clipper.m_dwFlags |= RefClipper::RCLIP_DIRTY_VIEWRECT;
// get render target; update it; put it back
RDRenderTarget *pRendTgt = this->GetRenderTarget();
pRendTgt->m_Clip.left = pVpt->dwX;
pRendTgt->m_Clip.top = pVpt->dwY;
pRendTgt->m_Clip.right = pVpt->dwX + pVpt->dwWidth - 1;
pRendTgt->m_Clip.bottom = pVpt->dwY + pVpt->dwHeight - 1;
SetRenderTarget( pRendTgt );
return D3D_OK;
}
HRESULT
RefDev::Dp2SetWRange(LPD3DHAL_DP2COMMAND pCmd)
{
LPD3DHAL_DP2WINFO pWInfo;
// Keep only the last viewport notification
pWInfo = (D3DHAL_DP2WINFO *)(pCmd + 1) + (pCmd->wStateCount - 1);
// get render target; update it; put it back
RDRenderTarget *pRendTgt = this->GetRenderTarget();
pRendTgt->m_fWRange[0] = pWInfo->dvWNear;
pRendTgt->m_fWRange[1] = pWInfo->dvWFar;
this->SetRenderTarget( pRendTgt );
return D3D_OK;
}
HRESULT
RefDev::Dp2SetZRange(LPD3DHAL_DP2COMMAND pCmd)
{
LPD3DHAL_DP2ZRANGE pZRange;
// Keep only the last viewport notification
pZRange = (D3DHAL_DP2ZRANGE *)(pCmd + 1) + (pCmd->wStateCount - 1);
// Update T&L viewport state
D3DVIEWPORT7& vp = m_Clipper.m_Viewport;
vp.dvMinZ = pZRange->dvMinZ;
vp.dvMaxZ = pZRange->dvMaxZ;
m_Clipper.m_dwFlags |= RefClipper::RCLIP_DIRTY_ZRANGE;
return D3D_OK;
}
HRESULT
RefDev::Dp2SetMaterial(LPD3DHAL_DP2COMMAND pCmd)
{
LPD3DHAL_DP2SETMATERIAL pSetMat;
// Keep only the last material notification
pSetMat = (D3DHAL_DP2SETMATERIAL *)(pCmd + 1) + (pCmd->wStateCount - 1);
m_RefVP.m_Material = *(D3DMATERIAL7 *)pSetMat;
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_MATERIAL;
return D3D_OK;
}
HRESULT
RefDev::Dp2CreateLight(LPD3DHAL_DP2COMMAND pCmd)
{
WORD wNumCreateLight = pCmd->wStateCount;
LPD3DHAL_DP2CREATELIGHT pCreateLight = (LPD3DHAL_DP2CREATELIGHT)(pCmd + 1);
HRESULT hr = D3D_OK;
for (int i = 0; i < wNumCreateLight; i++, pCreateLight++)
{
HR_RET(m_RefVP.GrowLightArray( pCreateLight->dwIndex ) );
}
return hr;
}
HRESULT
RefDev::Dp2SetLight(LPD3DHAL_DP2COMMAND pCmd,
LPDWORD pdwStride)
{
HRESULT hr = D3D_OK;
WORD wNumSetLight = pCmd->wStateCount;
_ASSERT( pdwStride != NULL, "pdwStride is Null" );
*pdwStride = sizeof(D3DHAL_DP2COMMAND);
LPD3DHAL_DP2SETLIGHT pSetLight = (LPD3DHAL_DP2SETLIGHT)(pCmd + 1);
D3DLIGHT7 *pLightData = NULL;
for (int i = 0; i < wNumSetLight; i++)
{
DWORD dwStride = sizeof(D3DHAL_DP2SETLIGHT);
DWORD dwIndex = pSetLight->dwIndex;
// Assert that create was not called here
_ASSERTf( m_RefVP.m_LightArray.IsValidIndex( dwIndex ),
( "Create was not called prior to the SetLight for light %d",
dwIndex ));
switch (pSetLight->dwDataType)
{
case D3DHAL_SETLIGHT_ENABLE:
m_RefVP.LightEnable( dwIndex, TRUE );
break;
case D3DHAL_SETLIGHT_DISABLE:
m_RefVP.LightEnable( dwIndex, FALSE );
break;
case D3DHAL_SETLIGHT_DATA:
pLightData = (D3DLIGHT7 *)((LPBYTE)pSetLight + dwStride);
dwStride += sizeof(D3DLIGHT7);
HR_RET(m_RefVP.SetLightData( pSetLight->dwIndex, pLightData));
break;
default:
DPFERR( "Unknown SetLight command" );
hr = DDERR_INVALIDPARAMS;
}
*pdwStride += dwStride;
// Update the command buffer pointer
pSetLight = (D3DHAL_DP2SETLIGHT *)((LPBYTE)pSetLight +
dwStride);
}
return hr;
}
static D3DMATRIX matIdent =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
HRESULT
RefDev::Dp2SetTransform(LPD3DHAL_DP2COMMAND pCmd)
{
WORD wNumXfrms = pCmd->wStateCount;
D3DHAL_DP2SETTRANSFORM *pSetXfrm = (D3DHAL_DP2SETTRANSFORM*)(pCmd + 1);
for (int i = 0; i < (int) wNumXfrms; i++, pSetXfrm++)
{
D3DMATRIX* pMat = &pSetXfrm->matrix;
DWORD xfrmType = (DWORD)pSetXfrm->xfrmType;
if ((DWORD)xfrmType >= RD_WORLDMATRIXBASE &&
(DWORD)xfrmType < (RD_WORLDMATRIXBASE + RD_MAX_WORLD_MATRICES))
{
// World matrix is set
UINT index = (DWORD)xfrmType - RD_WORLDMATRIXBASE;
memcpy(&(m_RefVP.m_xfmWorld[index]), pMat, sizeof(D3DMATRIX));
switch (index)
{
case 0:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLDXFM;
break;
case 1:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD1XFM;
break;
case 2:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD2XFM;
break;
case 3:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD3XFM;
break;
default:
// m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLDNXFM;
break;
}
}
else
{
switch( xfrmType )
{
case D3DTRANSFORMSTATE_WORLD_DX7:
memcpy(&(m_RefVP.m_xfmWorld[0]), pMat, sizeof(D3DMATRIX));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLDXFM;
break;
case D3DTRANSFORMSTATE_VIEW:
memcpy(&m_RefVP.m_xfmView, pMat, sizeof(D3DMATRIX));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_VIEWXFM;
break;
case D3DTRANSFORMSTATE_PROJECTION:
memcpy(&m_RefVP.m_xfmProj, pMat, sizeof(D3DMATRIX));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_PROJXFM;
break;
case D3DTRANSFORMSTATE_WORLD1_DX7:
memcpy(&(m_RefVP.m_xfmWorld[1]), pMat, sizeof(D3DMATRIX));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD1XFM;
break;
case D3DTRANSFORMSTATE_WORLD2_DX7:
memcpy(&(m_RefVP.m_xfmWorld[2]), pMat, sizeof(D3DMATRIX));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD2XFM;
break;
case D3DTRANSFORMSTATE_WORLD3_DX7:
memcpy(&(m_RefVP.m_xfmWorld[3]), pMat, sizeof(D3DMATRIX));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD3XFM;
break;
case D3DTRANSFORMSTATE_TEXTURE0:
case D3DTRANSFORMSTATE_TEXTURE1:
case D3DTRANSFORMSTATE_TEXTURE2:
case D3DTRANSFORMSTATE_TEXTURE3:
case D3DTRANSFORMSTATE_TEXTURE4:
case D3DTRANSFORMSTATE_TEXTURE5:
case D3DTRANSFORMSTATE_TEXTURE6:
case D3DTRANSFORMSTATE_TEXTURE7:
memcpy(
&(m_RefVP.m_xfmTex[xfrmType - D3DTRANSFORMSTATE_TEXTURE0]),
pMat, sizeof(D3DMATRIX)
);
break;
default:
DPFERR( "Ignoring unknown transform type" );
}
}
}
return D3D_OK;
}
extern void MatrixProduct(D3DMATRIX *result, D3DMATRIX *a, D3DMATRIX *b);
HRESULT
RefDev::Dp2MultiplyTransform(LPD3DHAL_DP2COMMAND pCmd)
{
WORD wNumXfrms = pCmd->wStateCount;
D3DHAL_DP2MULTIPLYTRANSFORM *pSetXfrm = (D3DHAL_DP2MULTIPLYTRANSFORM*)(pCmd + 1);
for (int i = 0; i < (int) wNumXfrms; i++, pSetXfrm++)
{
D3DMATRIX* pMat = &pSetXfrm->matrix;
DWORD xfrmType = (DWORD)pSetXfrm->xfrmType;
if ((DWORD)xfrmType >= RD_WORLDMATRIXBASE &&
(DWORD)xfrmType < (RD_WORLDMATRIXBASE + RD_MAX_WORLD_MATRICES))
{
// World matrix is set
UINT index = (DWORD)xfrmType - RD_WORLDMATRIXBASE;
MatrixProduct(&(m_RefVP.m_xfmWorld[index]), pMat,
&(m_RefVP.m_xfmWorld[index]));
switch (index)
{
case 0:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLDXFM;
break;
case 1:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD1XFM;
break;
case 2:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD2XFM;
break;
case 3:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD3XFM;
break;
default:
// m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLDNXFM;
break;
}
}
else
{
switch( xfrmType )
{
case D3DTRANSFORMSTATE_WORLD_DX7:
MatrixProduct(&(m_RefVP.m_xfmWorld[0]), pMat,
&(m_RefVP.m_xfmWorld[0]));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLDXFM;
break;
case D3DTRANSFORMSTATE_VIEW:
MatrixProduct(&m_RefVP.m_xfmView, pMat, &m_RefVP.m_xfmView);
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_VIEWXFM;
break;
case D3DTRANSFORMSTATE_PROJECTION:
MatrixProduct(&m_RefVP.m_xfmProj, pMat, &m_RefVP.m_xfmProj);
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_PROJXFM;
break;
case D3DTRANSFORMSTATE_WORLD1_DX7:
MatrixProduct(&(m_RefVP.m_xfmWorld[1]), pMat,
&(m_RefVP.m_xfmWorld[1]));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD1XFM;
break;
case D3DTRANSFORMSTATE_WORLD2_DX7:
MatrixProduct(&(m_RefVP.m_xfmWorld[2]), pMat,
&(m_RefVP.m_xfmWorld[2]));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD2XFM;
break;
case D3DTRANSFORMSTATE_WORLD3_DX7:
MatrixProduct(&(m_RefVP.m_xfmWorld[3]), pMat,
&(m_RefVP.m_xfmWorld[3]));
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_WORLD3XFM;
break;
case D3DTRANSFORMSTATE_TEXTURE0:
case D3DTRANSFORMSTATE_TEXTURE1:
case D3DTRANSFORMSTATE_TEXTURE2:
case D3DTRANSFORMSTATE_TEXTURE3:
case D3DTRANSFORMSTATE_TEXTURE4:
case D3DTRANSFORMSTATE_TEXTURE5:
case D3DTRANSFORMSTATE_TEXTURE6:
case D3DTRANSFORMSTATE_TEXTURE7:
MatrixProduct(
&(m_RefVP.m_xfmTex[xfrmType - D3DTRANSFORMSTATE_TEXTURE0]),
pMat,
&(m_RefVP.m_xfmTex[xfrmType - D3DTRANSFORMSTATE_TEXTURE0])
);
break;
default:
DPFERR( "Ignoring unknown transform type" );
}
}
}
return D3D_OK;
}
HRESULT
RefDev::Dp2SetClipPlane(LPD3DHAL_DP2COMMAND pCmd)
{
WORD wNumClipPlanes = pCmd->wStateCount;
LPD3DHAL_DP2SETCLIPPLANE pSetClipPlane =
(LPD3DHAL_DP2SETCLIPPLANE)(pCmd + 1);
for (int i = 0; i < (int) wNumClipPlanes; i++, pSetClipPlane++)
{
_ASSERTf( pSetClipPlane->dwIndex < RD_MAX_USER_CLIPPLANES,
("Refrast does not support %d clip planes",
pSetClipPlane->dwIndex ) );
memcpy( &(m_Clipper.m_userClipPlanes[pSetClipPlane->dwIndex]),
pSetClipPlane->plane, sizeof(RDVECTOR4) );
}
return D3D_OK;
}
HRESULT
RefDev::Dp2SetExtention(LPD3DHAL_DP2COMMAND pCmd)
{
return D3D_OK;
}
HRESULT
RefDev::Dp2RecRenderStates(DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd,
LPDWORD lpdwRuntimeRStates )
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2RENDERSTATE);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecTextureStageState(DWORD dwFvf, LPD3DHAL_DP2COMMAND pCmd )
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2TEXTURESTAGESTATE);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecViewport(LPD3DHAL_DP2COMMAND pCmd)
{
return RecordLastState(pCmd, sizeof(D3DHAL_DP2VIEWPORTINFO));
}
HRESULT
RefDev::Dp2RecWRange(LPD3DHAL_DP2COMMAND pCmd)
{
return RecordLastState(pCmd, sizeof(D3DHAL_DP2WINFO));
}
HRESULT
RefDev::Dp2RecZRange(LPD3DHAL_DP2COMMAND pCmd)
{
return RecordLastState(pCmd, sizeof(D3DHAL_DP2ZRANGE));
}
HRESULT
RefDev::Dp2RecMaterial(LPD3DHAL_DP2COMMAND pCmd)
{
return RecordLastState(pCmd, sizeof(D3DHAL_DP2SETMATERIAL));
}
HRESULT
RefDev::Dp2RecCreateLight(LPD3DHAL_DP2COMMAND pCmd)
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2CREATELIGHT);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecSetLight(LPD3DHAL_DP2COMMAND pCmd,
LPDWORD pdwStride)
{
WORD wNumSetLight = pCmd->wStateCount;
_ASSERT(pdwStride != NULL, "pdwStride is NULL" );
*pdwStride = sizeof(D3DHAL_DP2COMMAND);
LPD3DHAL_DP2SETLIGHT pSetLight = (LPD3DHAL_DP2SETLIGHT)(pCmd + 1);
for (int i = 0; i < wNumSetLight; i++)
{
DWORD dwStride = sizeof(D3DHAL_DP2SETLIGHT);
switch (pSetLight->dwDataType)
{
case D3DHAL_SETLIGHT_ENABLE:
break;
case D3DHAL_SETLIGHT_DISABLE:
break;
case D3DHAL_SETLIGHT_DATA:
dwStride += sizeof(D3DLIGHT7);
break;
}
*pdwStride += dwStride;
// Update the command buffer pointer
pSetLight = (D3DHAL_DP2SETLIGHT *)((LPBYTE)pSetLight +
dwStride);
}
return RecordStates((PUINT8)pCmd, *pdwStride);
}
HRESULT
RefDev::Dp2RecTransform(LPD3DHAL_DP2COMMAND pCmd)
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2SETTRANSFORM);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecExtention(LPD3DHAL_DP2COMMAND pCmd)
{
return D3D_OK;
}
HRESULT
RefDev::Dp2RecClipPlane(LPD3DHAL_DP2COMMAND pCmd)
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2SETCLIPPLANE);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecSetVertexShader(LPD3DHAL_DP2COMMAND pCmd)
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2VERTEXSHADER);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecSetVertexShaderConsts( DWORD StartReg,
DWORD dwCount,
LPDWORD pData )
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) +
dwCount*4*sizeof(float);
LPBYTE pBytes = new BYTE[dwSize];
if( pBytes == NULL ) return DDERR_OUTOFMEMORY;
LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)pBytes;
LPD3DHAL_DP2SETVERTEXSHADERCONST pSVC =
(LPD3DHAL_DP2SETVERTEXSHADERCONST)(pCmd + 1);
LPDWORD pStuff = (LPDWORD)(pSVC + 1);
// Set up pCmd
pCmd->bCommand = D3DDP2OP_SETVERTEXSHADERCONST;
pCmd->wStateCount = 1;
// Set up pSVC
pSVC->dwRegister = StartReg;
pSVC->dwCount = dwCount;
// Copy the data
memcpy( pStuff, pData, dwCount*4*sizeof(float));
HRESULT hr = RecordStates(pBytes, dwSize);
delete [] pBytes;
return hr;
}
HRESULT
RefDev::Dp2RecSetPixelShader(LPD3DHAL_DP2COMMAND pCmd)
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2PIXELSHADER);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecSetPixelShaderConsts( DWORD StartReg,
DWORD dwCount,
LPDWORD pData )
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2SETPIXELSHADERCONST) +
dwCount*4*sizeof(float);
LPBYTE pBytes = new BYTE[dwSize];
if( pBytes == NULL ) return DDERR_OUTOFMEMORY;
LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)pBytes;
LPD3DHAL_DP2SETPIXELSHADERCONST pSVC =
(LPD3DHAL_DP2SETPIXELSHADERCONST)(pCmd + 1);
LPDWORD pStuff = (LPDWORD)(pSVC + 1);
// Set up pCmd
pCmd->bCommand = D3DDP2OP_SETPIXELSHADERCONST;
pCmd->wStateCount = 1;
// Set up pSVC
pSVC->dwRegister = StartReg;
pSVC->dwCount = dwCount;
// Copy the data
memcpy( pStuff, pData, dwCount*4*sizeof(float));
HRESULT hr = RecordStates(pBytes, dwSize);
delete [] pBytes;
return hr;
}
HRESULT
RefDev::Dp2RecSetStreamSource(LPD3DHAL_DP2COMMAND pCmd)
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2SETSTREAMSOURCE);
return RecordStates((PUINT8)pCmd, dwSize);
}
HRESULT
RefDev::Dp2RecSetIndices(LPD3DHAL_DP2COMMAND pCmd)
{
DWORD dwSize = sizeof(D3DHAL_DP2COMMAND) +
pCmd->wStateCount * sizeof(D3DHAL_DP2SETINDICES);
return RecordStates((PUINT8)pCmd, dwSize);
}
//-----------------------------------------------------------------------------
//
// RecordStates - This function copies the state data into the internal stateset
// buffer. It assumes that the current state set has already been properly set
// up in BeginStateSet().
//
//-----------------------------------------------------------------------------
HRESULT
RefDev::RecordStates(PUINT8 pData, DWORD dwSize)
{
HRESULT ret;
LPStateSetData pCurStateSets = m_pStateSets.CurrentItem();
DWORD dwCurIdx = pCurStateSets->CurrentIndex();
// Check if the buffer has enough space
if( (ret = pCurStateSets->CheckAndGrow(dwCurIdx + dwSize,
RD_STATESET_GROWDELTA)) != D3D_OK )
{
return ret;
}
// Copy the data and update the ptr.
PUINT8 pDest = (PUINT8)&((*pCurStateSets)[dwCurIdx]);
memcpy(pDest, pData, dwSize);
pCurStateSets->SetCurrentIndex(dwCurIdx + dwSize);
return D3D_OK;
}
HRESULT RefDev::RecordLastState(LPD3DHAL_DP2COMMAND pCmd,
DWORD dwUnitSize)
{
_ASSERT(pCmd->wStateCount != 0, "Number of states to record is zero" );
if( pCmd->wStateCount == 1 )
{
return RecordStates((PUINT8)pCmd, sizeof(D3DHAL_DP2COMMAND) + dwUnitSize);
}
else
{
HRESULT ret;
WORD wCount = pCmd->wStateCount;
pCmd->wStateCount = 1;
ret = RecordStates((PUINT8)pCmd, sizeof(D3DHAL_DP2COMMAND));
if( ret != D3D_OK )
{
return ret;
}
ret = RecordStates((PUINT8)(pCmd + 1) + dwUnitSize * (wCount - 1),
dwUnitSize);
if( ret != D3D_OK )
{
return ret;
}
pCmd->wStateCount = wCount;
return D3D_OK;
}
}
HRESULT
RefDev::BeginStateSet(DWORD dwHandle)
{
HRESULT ret;
// Grow the array if no more space left
if( (ret = m_pStateSets.CheckAndGrow(dwHandle)) != D3D_OK )
{
return ret;
}
_ASSERT(m_pStateSets[dwHandle] == NULL, "pStateSets array is NULL" );
// Create the new StateSet
LPStateSetData pNewStateSet = new StateSetData;
if( pNewStateSet == NULL )
{
return DDERR_OUTOFMEMORY;
}
m_pStateSets.SetCurrentIndex(dwHandle);
m_pStateSets.SetCurrentItem(pNewStateSet);
// Switch to record mode
SetRecStateFunctions();
return D3D_OK;
}
HRESULT
RefDev::EndStateSet(void)
{
// Switch to execute mode
SetSetStateFunctions();
return D3D_OK;
}
HRESULT
RefDev::ExecuteStateSet(DWORD dwHandle)
{
HRESULT ret;
if( (ret = m_pStateSets.CheckRange(dwHandle)) != D3D_OK )
{
return ret;
}
LPStateSetData pStateSet = m_pStateSets[dwHandle];
if( pStateSet == NULL )
{
return DDERR_INVALIDPARAMS;
}
LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)&((*pStateSet)[0]);
UINT_PTR CmdBoundary = (UINT_PTR)pCmd + pStateSet->CurrentIndex();
// Loop through the data, update render states
for (;;)
{
ret = DrawPrimitives2( NULL,
(UINT16)0,
(DWORD)0,
0,
&pCmd,
NULL );
if( ret != D3D_OK )
{
return ret;
}
if( (UINT_PTR)pCmd >= CmdBoundary )
break;
}
return D3D_OK;
}
HRESULT
RefDev::DeleteStateSet(DWORD dwHandle)
{
HRESULT ret;
if( (ret = m_pStateSets.CheckRange(dwHandle)) != D3D_OK )
{
return ret;
}
if( m_pStateSets[dwHandle] != NULL )
{
delete m_pStateSets[dwHandle];
m_pStateSets[dwHandle] = NULL;
}
return D3D_OK;
}
HRESULT
RefDev::CaptureStateSet(DWORD dwHandle)
{
HRESULT ret;
if( (ret = m_pStateSets.CheckRange(dwHandle)) != D3D_OK )
{
return ret;
}
LPStateSetData pStateSet = m_pStateSets[dwHandle];
if( pStateSet == NULL )
{
return DDERR_INVALIDPARAMS;
}
BYTE *p = &((*pStateSet)[0]);
UINT_PTR pEnd = (UINT_PTR)(p + pStateSet->CurrentIndex());
while((UINT_PTR)p < pEnd)
{
LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)p;
p += sizeof(D3DHAL_DP2COMMAND);
switch(pCmd->bCommand)
{
case D3DDP2OP_RENDERSTATE:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2RENDERSTATE pData = (LPD3DHAL_DP2RENDERSTATE)p;
pData->dwState = GetRS()[pData->RenderState];
p += sizeof(D3DHAL_DP2RENDERSTATE);
}
break;
}
case D3DDP2OP_SETLIGHT:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETLIGHT pData = (LPD3DHAL_DP2SETLIGHT)p;
p += sizeof(D3DHAL_DP2SETLIGHT);
if( !m_RefVP.m_LightArray.IsValidIndex( pData->dwIndex ) )
{
DPFERR( "The light index in capture is invalid\n" );
return D3DERR_INVALIDCALL;
}
switch (pData->dwDataType)
{
case D3DHAL_SETLIGHT_ENABLE:
if(!m_RefVP.m_LightArray[pData->dwIndex].IsEnabled())
pData->dwDataType = D3DHAL_SETLIGHT_DISABLE;
break;
case D3DHAL_SETLIGHT_DISABLE:
if(m_RefVP.m_LightArray[pData->dwIndex].IsEnabled())
pData->dwDataType = D3DHAL_SETLIGHT_ENABLE;
break;
case D3DHAL_SETLIGHT_DATA:
m_RefVP.m_LightArray[pData->dwIndex].GetLight((LPD3DLIGHT7)p);
p += sizeof(D3DLIGHT7);
break;
}
}
break;
}
case D3DDP2OP_SETMATERIAL:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETMATERIAL pData = (LPD3DHAL_DP2SETMATERIAL)p;
*pData = m_RefVP.m_Material;
p += sizeof(D3DHAL_DP2SETMATERIAL);
}
break;
}
case D3DDP2OP_SETTRANSFORM:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETTRANSFORM pData = (LPD3DHAL_DP2SETTRANSFORM)p;
switch(pData->xfrmType)
{
case D3DTRANSFORMSTATE_WORLD:
pData->matrix = m_RefVP.m_xfmWorld[0];
break;
case D3DTRANSFORMSTATE_WORLD1:
pData->matrix = m_RefVP.m_xfmWorld[1];
break;
case D3DTRANSFORMSTATE_WORLD2:
pData->matrix = m_RefVP.m_xfmWorld[2];
break;
case D3DTRANSFORMSTATE_WORLD3:
pData->matrix = m_RefVP.m_xfmWorld[3];
break;
case D3DTRANSFORMSTATE_VIEW:
pData->matrix = m_RefVP.m_xfmView;
break;
case D3DTRANSFORMSTATE_PROJECTION:
pData->matrix = m_RefVP.m_xfmProj;
break;
case D3DTRANSFORMSTATE_TEXTURE0:
case D3DTRANSFORMSTATE_TEXTURE1:
case D3DTRANSFORMSTATE_TEXTURE2:
case D3DTRANSFORMSTATE_TEXTURE3:
case D3DTRANSFORMSTATE_TEXTURE4:
case D3DTRANSFORMSTATE_TEXTURE5:
case D3DTRANSFORMSTATE_TEXTURE6:
case D3DTRANSFORMSTATE_TEXTURE7:
pData->matrix = m_RefVP.m_xfmTex[pData->xfrmType - D3DTRANSFORMSTATE_TEXTURE0];
break;
default:
if( ((DWORD)pData->xfrmType >= RD_WORLDMATRIXBASE) &&
((DWORD)pData->xfrmType < (RD_WORLDMATRIXBASE +
RD_MAX_WORLD_MATRICES)) )
{
pData->matrix = m_RefVP.m_xfmWorld[
(DWORD)pData->xfrmType - RD_WORLDMATRIXBASE];
}
else
{
DPFERR( "Ignoring unknown transform type" );
return D3DERR_INVALIDCALL;
}
break;
}
p += sizeof(D3DHAL_DP2SETTRANSFORM);
}
break;
}
case D3DDP2OP_TEXTURESTAGESTATE:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2TEXTURESTAGESTATE pData = (LPD3DHAL_DP2TEXTURESTAGESTATE)p;
pData->dwValue = m_TextureStageState[pData->wStage].m_dwVal[pData->TSState];
p += sizeof(D3DHAL_DP2TEXTURESTAGESTATE);
}
break;
}
case D3DDP2OP_VIEWPORTINFO:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
D3DVIEWPORT7 viewport;
LPD3DHAL_DP2VIEWPORTINFO lpVwpData = (LPD3DHAL_DP2VIEWPORTINFO)p;
D3DVIEWPORT7& vp = m_Clipper.m_Viewport;
lpVwpData->dwX = vp.dwX;
lpVwpData->dwY = vp.dwY;
lpVwpData->dwWidth = vp.dwWidth;
lpVwpData->dwHeight = vp.dwHeight;
p += sizeof(D3DHAL_DP2VIEWPORTINFO);
}
break;
}
case D3DDP2OP_ZRANGE:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2ZRANGE pData = (LPD3DHAL_DP2ZRANGE)p;
D3DVIEWPORT7& vp = m_Clipper.m_Viewport;
pData->dvMinZ = vp.dvMinZ;
pData->dvMaxZ = vp.dvMaxZ;
p += sizeof(D3DHAL_DP2ZRANGE);
}
break;
}
case D3DDP2OP_SETCLIPPLANE:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETCLIPPLANE pData = (LPD3DHAL_DP2SETCLIPPLANE)p;
*((RDVECTOR4 *)pData->plane) =
m_Clipper.m_userClipPlanes[pData->dwIndex];
p += sizeof(D3DHAL_DP2SETCLIPPLANE);
}
break;
}
case D3DDP2OP_SETVERTEXSHADER:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2VERTEXSHADER pData = (LPD3DHAL_DP2VERTEXSHADER)p;
pData->dwHandle = m_CurrentVShaderHandle;
p += sizeof(D3DHAL_DP2VERTEXSHADER);
}
break;
}
case D3DDP2OP_SETVERTEXSHADERCONST:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETVERTEXSHADERCONST pData =
(LPD3DHAL_DP2SETVERTEXSHADERCONST)p;
m_RefVM.GetData( D3DSPR_CONST, pData->dwRegister,
pData->dwCount, (LPVOID)(pData+1) );
p += (sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) +
(pData->dwCount<<4));
}
break;
}
case D3DDP2OP_SETSTREAMSOURCE:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETSTREAMSOURCE pData =
(LPD3DHAL_DP2SETSTREAMSOURCE)p;
pData->dwVBHandle = m_VStream[pData->dwStream].m_dwHandle;
pData->dwStride = m_VStream[pData->dwStream].m_dwStride;
p += sizeof(D3DHAL_DP2SETSTREAMSOURCE);
}
break;
}
case D3DDP2OP_SETINDICES:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETINDICES pData =
(LPD3DHAL_DP2SETINDICES)p;
pData->dwVBHandle = m_IndexStream.m_dwHandle;
pData->dwStride = m_IndexStream.m_dwStride;
p += sizeof(D3DHAL_DP2SETINDICES);
}
break;
}
case D3DDP2OP_SETPIXELSHADER:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2PIXELSHADER pData = (LPD3DHAL_DP2PIXELSHADER)p;
pData->dwHandle = m_CurrentPShaderHandle;
p += sizeof(D3DHAL_DP2PIXELSHADER);
}
break;
}
case D3DDP2OP_SETPIXELSHADERCONST:
{
for(DWORD i = 0; i < (DWORD)pCmd->wStateCount; ++i)
{
LPD3DHAL_DP2SETPIXELSHADERCONST pData =
(LPD3DHAL_DP2SETPIXELSHADERCONST)p;
FLOAT* pfData = (FLOAT*)(pData+1);
for (UINT iR=pData->dwRegister; iR<pData->dwCount; iR++)
{
*(pfData+0) = m_Rast.m_ConstReg[iR][0][0];
*(pfData+1) = m_Rast.m_ConstReg[iR][0][1];
*(pfData+2) = m_Rast.m_ConstReg[iR][0][2];
*(pfData+3) = m_Rast.m_ConstReg[iR][0][3];
pfData += 4;
}
p += (sizeof(D3DHAL_DP2SETPIXELSHADERCONST) +
(pData->dwCount<<4));
}
break;
}
default:
_ASSERT(FALSE, "Ununderstood DP2 command in Capture");
}
}
return D3D_OK;
}
HRESULT
RefDev::CreateStateSet(DWORD dwHandle, D3DSTATEBLOCKTYPE sbType)
{
HRESULT hr = S_OK;
// This DDI should be called only for drivers > DX7
// and only for those which support TLHals.
// It is called only when the device created is a pure-device
// We need to add filtering code in DX9 to make the DDI emulation
// work.
_ASSERT( m_dwDDIType > RDDDI_DX8HAL, "This DDI should be called only"
" for DX8TL\n" );
// Begin a new stateset
if( FAILED( hr = BeginStateSet( dwHandle ) ) )
{
DPFERR( "CreateStateSet: Begin failed\n" );
return hr;
}
switch( sbType )
{
case D3DSBT_VERTEXSTATE:
hr = RecordVertexState( dwHandle );
if( FAILED( hr ) )
{
DPFERR( "RecordVertexState failed\n" );
}
break;
case D3DSBT_PIXELSTATE:
hr = RecordPixelState( dwHandle );
if( FAILED( hr ) )
{
DPFERR( "RecordPixelState failed\n" );
}
break;
case D3DSBT_ALL:
hr = RecordAllState( dwHandle );
if( FAILED( hr ) )
{
DPFERR( "RecordAllState failed\n" );
}
break;
default:
DPFERR( "Unknown StateBlock type for Creation\n" );
hr = D3DERR_INVALIDCALL;
}
EndStateSet();
return hr;
}
HRESULT
RefDev::RecordAllState( DWORD dwHandle )
{
DWORD data_size = 0;
DWORD i = 0;
DWORD j = 0;
GArrayT<BYTE> data;
LPD3DHAL_DP2COMMAND pCmd = NULL;
HRESULT hr = S_OK;
static D3DRENDERSTATETYPE rstates[] =
{
D3DRENDERSTATE_SPECULARENABLE,
D3DRENDERSTATE_ZENABLE,
D3DRENDERSTATE_FILLMODE,
D3DRENDERSTATE_SHADEMODE,
D3DRENDERSTATE_LINEPATTERN,
D3DRENDERSTATE_ZWRITEENABLE,
D3DRENDERSTATE_ALPHATESTENABLE,
D3DRENDERSTATE_LASTPIXEL,
D3DRENDERSTATE_SRCBLEND,
D3DRENDERSTATE_DESTBLEND,
D3DRENDERSTATE_CULLMODE,
D3DRENDERSTATE_ZFUNC,
D3DRENDERSTATE_ALPHAREF,
D3DRENDERSTATE_ALPHAFUNC,
D3DRENDERSTATE_DITHERENABLE,
D3DRENDERSTATE_FOGENABLE,
D3DRENDERSTATE_STIPPLEDALPHA,
D3DRENDERSTATE_FOGCOLOR,
D3DRENDERSTATE_FOGTABLEMODE,
D3DRENDERSTATE_FOGSTART,
D3DRENDERSTATE_FOGEND,
D3DRENDERSTATE_FOGDENSITY,
D3DRENDERSTATE_EDGEANTIALIAS,
D3DRENDERSTATE_ALPHABLENDENABLE,
D3DRENDERSTATE_ZBIAS,
D3DRENDERSTATE_RANGEFOGENABLE,
D3DRENDERSTATE_STENCILENABLE,
D3DRENDERSTATE_STENCILFAIL,
D3DRENDERSTATE_STENCILZFAIL,
D3DRENDERSTATE_STENCILPASS,
D3DRENDERSTATE_STENCILFUNC,
D3DRENDERSTATE_STENCILREF,
D3DRENDERSTATE_STENCILMASK,
D3DRENDERSTATE_STENCILWRITEMASK,
D3DRENDERSTATE_TEXTUREFACTOR,
D3DRENDERSTATE_WRAP0,
D3DRENDERSTATE_WRAP1,
D3DRENDERSTATE_WRAP2,
D3DRENDERSTATE_WRAP3,
D3DRENDERSTATE_WRAP4,
D3DRENDERSTATE_WRAP5,
D3DRENDERSTATE_WRAP6,
D3DRENDERSTATE_WRAP7,
D3DRENDERSTATE_AMBIENT,
D3DRENDERSTATE_COLORVERTEX,
D3DRENDERSTATE_FOGVERTEXMODE,
D3DRENDERSTATE_CLIPPING,
D3DRENDERSTATE_LIGHTING,
D3DRENDERSTATE_NORMALIZENORMALS,
D3DRENDERSTATE_LOCALVIEWER,
D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,
D3DRENDERSTATE_AMBIENTMATERIALSOURCE,
D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,
D3DRENDERSTATE_SPECULARMATERIALSOURCE,
D3DRENDERSTATE_VERTEXBLEND,
D3DRENDERSTATE_CLIPPLANEENABLE,
D3DRS_SOFTWAREVERTEXPROCESSING,
D3DRS_POINTSIZE,
D3DRS_POINTSIZE_MIN,
D3DRS_POINTSPRITEENABLE,
D3DRS_POINTSCALEENABLE,
D3DRS_POINTSCALE_A,
D3DRS_POINTSCALE_B,
D3DRS_POINTSCALE_C,
D3DRS_MULTISAMPLEANTIALIAS,
D3DRS_MULTISAMPLEMASK,
D3DRS_PATCHEDGESTYLE,
D3DRS_PATCHSEGMENTS,
D3DRS_POINTSIZE_MAX,
D3DRS_INDEXEDVERTEXBLENDENABLE,
D3DRS_COLORWRITEENABLE,
D3DRS_TWEENFACTOR,
D3DRS_BLENDOP,
};
static D3DTEXTURESTAGESTATETYPE tsstates[] =
{
D3DTSS_COLOROP,
D3DTSS_COLORARG1,
D3DTSS_COLORARG2,
D3DTSS_ALPHAOP,
D3DTSS_ALPHAARG1,
D3DTSS_ALPHAARG2,
D3DTSS_BUMPENVMAT00,
D3DTSS_BUMPENVMAT01,
D3DTSS_BUMPENVMAT10,
D3DTSS_BUMPENVMAT11,
D3DTSS_TEXCOORDINDEX,
D3DTSS_ADDRESSU,
D3DTSS_ADDRESSV,
D3DTSS_BORDERCOLOR,
D3DTSS_MAGFILTER,
D3DTSS_MINFILTER,
D3DTSS_MIPFILTER,
D3DTSS_MIPMAPLODBIAS,
D3DTSS_MAXMIPLEVEL,
D3DTSS_MAXANISOTROPY,
D3DTSS_BUMPENVLSCALE,
D3DTSS_BUMPENVLOFFSET,
D3DTSS_TEXTURETRANSFORMFLAGS,
D3DTSS_ADDRESSW,
D3DTSS_COLORARG0,
D3DTSS_ALPHAARG0,
D3DTSS_RESULTARG,
};
//
// !!! Dont Capture vertex streams !!!
// !!! Dont Capture index streams !!!
// !!! Dont Capture textures !!!
//
//
// Capture render-states
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2RENDERSTATE) *
sizeof(rstates)/sizeof(D3DRENDERSTATETYPE);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = sizeof(rstates)/sizeof(D3DRENDERSTATETYPE);
pCmd->bCommand = D3DDP2OP_RENDERSTATE;
D3DHAL_DP2RENDERSTATE* pRS = (D3DHAL_DP2RENDERSTATE*)(pCmd + 1);
for( i = 0; i < sizeof(rstates)/sizeof(D3DRENDERSTATETYPE); ++i)
{
pRS->RenderState = rstates[i];
pRS->dwState = GetRS()[rstates[i]];
pRS++;
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture texture-stage-states
//
data_size = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2TEXTURESTAGESTATE) *
sizeof(tsstates)/sizeof(D3DTEXTURESTAGESTATETYPE)
* D3DHAL_TSS_MAXSTAGES;
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = sizeof(tsstates)/sizeof(D3DTEXTURESTAGESTATETYPE)
* D3DHAL_TSS_MAXSTAGES;
pCmd->bCommand = D3DDP2OP_TEXTURESTAGESTATE;
D3DHAL_DP2TEXTURESTAGESTATE* pTSS = (D3DHAL_DP2TEXTURESTAGESTATE*)(pCmd+1);
for ( i = 0; i < D3DHAL_TSS_MAXSTAGES; i++ )
{
for( DWORD j = 0; j < sizeof(tsstates)/
sizeof(D3DTEXTURESTAGESTATETYPE); ++j)
{
pTSS->wStage = i;
pTSS->TSState = tsstates[j];
pTSS->dwValue = GetTSS( i )[tsstates[j]];
pTSS++;
}
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture viewport
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2VIEWPORTINFO);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_VIEWPORTINFO;
D3DHAL_DP2VIEWPORTINFO* pVP = (D3DHAL_DP2VIEWPORTINFO*)(pCmd+1);
pVP->dwX = m_Clipper.m_Viewport.dwX;
pVP->dwY = m_Clipper.m_Viewport.dwY;
pVP->dwWidth = m_Clipper.m_Viewport.dwWidth;
pVP->dwHeight = m_Clipper.m_Viewport.dwHeight;
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2ZRANGE);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_ZRANGE;
D3DHAL_DP2ZRANGE* pZR = (D3DHAL_DP2ZRANGE*)(pCmd+1);
D3DVIEWPORT7& vp = m_Clipper.m_Viewport;
pZR->dvMinZ = m_Clipper.m_Viewport.dvMinZ;
pZR->dvMaxZ = m_Clipper.m_Viewport.dvMaxZ;
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture transforms
//
// All the world-matrices, view, projection and the texture matrices
// (one per stage)
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETTRANSFORM) *
(RD_MAX_WORLD_MATRICES + D3DHAL_TSS_MAXSTAGES + 2);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = RD_MAX_WORLD_MATRICES + D3DHAL_TSS_MAXSTAGES + 2;
pCmd->bCommand = D3DDP2OP_SETTRANSFORM;
D3DHAL_DP2SETTRANSFORM* pST = (D3DHAL_DP2SETTRANSFORM*)(pCmd+1);
for( i = 0; i < RD_MAX_WORLD_MATRICES; i++ )
{
pST->xfrmType = (D3DTRANSFORMSTATETYPE)(RD_WORLDMATRIXBASE + i);
pST->matrix = m_RefVP.m_xfmWorld[i];
pST++;
}
// View Matrix
pST->xfrmType = D3DTRANSFORMSTATE_VIEW;
pST->matrix = m_RefVP.m_xfmView;
pST++;
// Projection Matrix
pST->xfrmType = D3DTRANSFORMSTATE_PROJECTION;
pST->matrix = m_RefVP.m_xfmProj;
pST++;
// Texture Matrices
for( i = 0; i < D3DHAL_TSS_MAXSTAGES; i++ )
{
pST->xfrmType =
(D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + i);
pST->matrix = m_RefVP.m_xfmTex[i];
pST++;
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture clip-planes
//
data_size = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2SETCLIPPLANE) * RD_MAX_USER_CLIPPLANES;
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = RD_MAX_USER_CLIPPLANES;
pCmd->bCommand = D3DDP2OP_SETCLIPPLANE;
D3DHAL_DP2SETCLIPPLANE* pSCP = (D3DHAL_DP2SETCLIPPLANE*)(pCmd+1);
for( i = 0; i < RD_MAX_USER_CLIPPLANES; i++ )
{
pSCP->dwIndex = i;
for( j=0; j<4; j++ )
pSCP->plane[j] = m_Clipper.m_userClipPlanes[i].v[j];
pSCP++;
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture material
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETMATERIAL);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETMATERIAL;
D3DHAL_DP2SETMATERIAL* pSM = (D3DHAL_DP2SETMATERIAL*)(pCmd+1);
*pSM = m_RefVP.m_Material;
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture lights
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DLIGHT7) +
sizeof(D3DHAL_DP2SETLIGHT)*2;
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 2;
pCmd->bCommand = D3DDP2OP_SETLIGHT;
D3DHAL_DP2SETLIGHT* pSL = (D3DHAL_DP2SETLIGHT *)(pCmd + 1);
D3DHAL_DP2SETLIGHT* pSL2 = pSL + 1;
pSL2->dwDataType = D3DHAL_SETLIGHT_DATA;
for( i = 0; i < m_RefVP.m_LightArray.GetSize(); i++ )
{
if( m_RefVP.m_LightArray[i].IsRefered() )
{
pSL2->dwIndex = pSL->dwIndex = i;
if( m_RefVP.m_LightArray[i].IsEnabled() )
{
pSL->dwDataType = D3DHAL_SETLIGHT_ENABLE;
}
else
{
pSL->dwDataType = D3DHAL_SETLIGHT_DISABLE;
}
m_RefVP.m_LightArray[i].GetLight((D3DLIGHT7*)(pSL2 + 1));
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
}
}
//
// Capture current vertex shader
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2VERTEXSHADER);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETVERTEXSHADER;
D3DHAL_DP2VERTEXSHADER* pVS = (D3DHAL_DP2VERTEXSHADER*)(pCmd+1);
pVS->dwHandle = m_CurrentVShaderHandle;
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture current pixel shader
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2PIXELSHADER);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETPIXELSHADER;
D3DHAL_DP2PIXELSHADER* pPS = (D3DHAL_DP2PIXELSHADER*)(pCmd+1);
pPS->dwHandle = m_CurrentPShaderHandle;
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture vertex shader constants
//
data_size = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) + (RD_MAX_NUMCONSTREG << 4);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETVERTEXSHADERCONST;
D3DHAL_DP2SETVERTEXSHADERCONST* pVSC =
(D3DHAL_DP2SETVERTEXSHADERCONST*)(pCmd+1);
pVSC->dwRegister = 0;
pVSC->dwCount = RD_MAX_NUMCONSTREG;
m_RefVM.GetData( D3DSPR_CONST, pVSC->dwRegister, pVSC->dwCount,
(LPVOID)(pVSC+1) );
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture pixel shader constants
//
data_size = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2SETPIXELSHADERCONST) + (RDPS_MAX_NUMCONSTREG << 4);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETPIXELSHADERCONST;
D3DHAL_DP2SETPIXELSHADERCONST* pPSC =
(D3DHAL_DP2SETPIXELSHADERCONST*)(pCmd+1);
pPSC->dwRegister = 0;
pPSC->dwCount = RDPS_MAX_NUMCONSTREG;
FLOAT* pfData = (FLOAT*)(pPSC+1);
for (UINT iR=pPSC->dwRegister; iR<pPSC->dwCount; iR++)
{
*(pfData+0) = m_Rast.m_ConstReg[iR][0][0];
*(pfData+1) = m_Rast.m_ConstReg[iR][0][1];
*(pfData+2) = m_Rast.m_ConstReg[iR][0][2];
*(pfData+3) = m_Rast.m_ConstReg[iR][0][3];
pfData += 4;
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
return hr;
}
HRESULT
RefDev::RecordVertexState( DWORD dwHandle )
{
DWORD data_size = 0;
DWORD i = 0;
DWORD j = 0;
GArrayT<BYTE> data;
LPD3DHAL_DP2COMMAND pCmd = NULL;
HRESULT hr = S_OK;
static D3DRENDERSTATETYPE rstates[] =
{
D3DRENDERSTATE_SHADEMODE,
D3DRENDERSTATE_SPECULARENABLE,
D3DRENDERSTATE_CULLMODE,
D3DRENDERSTATE_FOGENABLE,
D3DRENDERSTATE_FOGCOLOR,
D3DRENDERSTATE_FOGTABLEMODE,
D3DRENDERSTATE_FOGSTART,
D3DRENDERSTATE_FOGEND,
D3DRENDERSTATE_FOGDENSITY,
D3DRENDERSTATE_RANGEFOGENABLE,
D3DRENDERSTATE_AMBIENT,
D3DRENDERSTATE_COLORVERTEX,
D3DRENDERSTATE_FOGVERTEXMODE,
D3DRENDERSTATE_CLIPPING,
D3DRENDERSTATE_LIGHTING,
D3DRENDERSTATE_NORMALIZENORMALS,
D3DRENDERSTATE_LOCALVIEWER,
D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,
D3DRENDERSTATE_AMBIENTMATERIALSOURCE,
D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,
D3DRENDERSTATE_SPECULARMATERIALSOURCE,
D3DRENDERSTATE_VERTEXBLEND,
D3DRENDERSTATE_CLIPPLANEENABLE,
D3DRS_SOFTWAREVERTEXPROCESSING,
D3DRS_POINTSIZE,
D3DRS_POINTSIZE_MIN,
D3DRS_POINTSPRITEENABLE,
D3DRS_POINTSCALEENABLE,
D3DRS_POINTSCALE_A,
D3DRS_POINTSCALE_B,
D3DRS_POINTSCALE_C,
D3DRS_MULTISAMPLEANTIALIAS,
D3DRS_MULTISAMPLEMASK,
D3DRS_PATCHEDGESTYLE,
D3DRS_PATCHSEGMENTS,
D3DRS_POINTSIZE_MAX,
D3DRS_INDEXEDVERTEXBLENDENABLE,
D3DRS_TWEENFACTOR,
};
static D3DTEXTURESTAGESTATETYPE tsstates[] =
{
D3DTSS_TEXCOORDINDEX,
D3DTSS_TEXTURETRANSFORMFLAGS
};
//
// Capture render-states
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2RENDERSTATE) *
sizeof(rstates)/sizeof(D3DRENDERSTATETYPE);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = sizeof(rstates)/sizeof(D3DRENDERSTATETYPE);
pCmd->bCommand = D3DDP2OP_RENDERSTATE;
D3DHAL_DP2RENDERSTATE* pRS = (D3DHAL_DP2RENDERSTATE*)(pCmd + 1);
for( i = 0; i < sizeof(rstates)/sizeof(D3DRENDERSTATETYPE); ++i)
{
pRS->RenderState = rstates[i];
pRS->dwState = GetRS()[rstates[i]];
pRS++;
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture texture-stage-states
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2TEXTURESTAGESTATE)
* sizeof(tsstates)/sizeof(D3DTEXTURESTAGESTATETYPE)
* D3DHAL_TSS_MAXSTAGES;
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = sizeof(tsstates)/sizeof(D3DTEXTURESTAGESTATETYPE)
* D3DHAL_TSS_MAXSTAGES;
pCmd->bCommand = D3DDP2OP_TEXTURESTAGESTATE;
D3DHAL_DP2TEXTURESTAGESTATE* pTSS = (D3DHAL_DP2TEXTURESTAGESTATE*)(pCmd+1);
for ( i = 0; i < D3DHAL_TSS_MAXSTAGES; i++ )
{
for( DWORD j = 0; j < sizeof(tsstates)/
sizeof(D3DTEXTURESTAGESTATETYPE); ++j)
{
pTSS->wStage = i;
pTSS->TSState = tsstates[j];
pTSS->dwValue = GetTSS( i )[tsstates[j]];
pTSS++;
}
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture lights
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DLIGHT7) +
sizeof(D3DHAL_DP2SETLIGHT)*2;
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 2;
pCmd->bCommand = D3DDP2OP_SETLIGHT;
D3DHAL_DP2SETLIGHT* pSL = (D3DHAL_DP2SETLIGHT *)(pCmd + 1);
D3DHAL_DP2SETLIGHT* pSL2 = pSL + 1;
pSL2->dwDataType = D3DHAL_SETLIGHT_DATA;
for( i = 0; i < m_RefVP.m_LightArray.GetSize(); i++ )
{
if( m_RefVP.m_LightArray[i].IsRefered() )
{
pSL2->dwIndex = pSL->dwIndex = i;
if( m_RefVP.m_LightArray[i].IsEnabled() )
{
pSL->dwDataType = D3DHAL_SETLIGHT_ENABLE;
}
else
{
pSL->dwDataType = D3DHAL_SETLIGHT_DISABLE;
}
m_RefVP.m_LightArray[i].GetLight((D3DLIGHT7*)(pSL2 + 1));
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
}
}
//
// Capture vertex shader constants
//
data_size = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) + (RD_MAX_NUMCONSTREG << 4);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETVERTEXSHADERCONST;
D3DHAL_DP2SETVERTEXSHADERCONST* pVSC =
(D3DHAL_DP2SETVERTEXSHADERCONST*)(pCmd+1);
pVSC->dwRegister = 0;
pVSC->dwCount = RD_MAX_NUMCONSTREG;
m_RefVM.GetData( D3DSPR_CONST, pVSC->dwRegister, pVSC->dwCount,
(LPVOID)(pVSC+1) );
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture current vertex shader
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2VERTEXSHADER);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETVERTEXSHADER;
D3DHAL_DP2VERTEXSHADER* pVS =
(D3DHAL_DP2VERTEXSHADER*)(pCmd+1);
pVS->dwHandle = m_CurrentVShaderHandle;
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
return hr;
}
HRESULT
RefDev::RecordPixelState( DWORD dwHandle )
{
DWORD data_size = 0;
DWORD i = 0;
DWORD j = 0;
GArrayT<BYTE> data;
LPD3DHAL_DP2COMMAND pCmd = NULL;
HRESULT hr = S_OK;
static D3DRENDERSTATETYPE rstates[] =
{
D3DRENDERSTATE_ZENABLE,
D3DRENDERSTATE_FILLMODE,
D3DRENDERSTATE_SHADEMODE,
D3DRENDERSTATE_LINEPATTERN,
D3DRENDERSTATE_ZWRITEENABLE,
D3DRENDERSTATE_ALPHATESTENABLE,
D3DRENDERSTATE_LASTPIXEL,
D3DRENDERSTATE_SRCBLEND,
D3DRENDERSTATE_DESTBLEND,
D3DRENDERSTATE_ZFUNC,
D3DRENDERSTATE_ALPHAREF,
D3DRENDERSTATE_ALPHAFUNC,
D3DRENDERSTATE_DITHERENABLE,
D3DRENDERSTATE_STIPPLEDALPHA,
D3DRENDERSTATE_FOGSTART,
D3DRENDERSTATE_FOGEND,
D3DRENDERSTATE_FOGDENSITY,
D3DRENDERSTATE_EDGEANTIALIAS,
D3DRENDERSTATE_ALPHABLENDENABLE,
D3DRENDERSTATE_ZBIAS,
D3DRENDERSTATE_STENCILENABLE,
D3DRENDERSTATE_STENCILFAIL,
D3DRENDERSTATE_STENCILZFAIL,
D3DRENDERSTATE_STENCILPASS,
D3DRENDERSTATE_STENCILFUNC,
D3DRENDERSTATE_STENCILREF,
D3DRENDERSTATE_STENCILMASK,
D3DRENDERSTATE_STENCILWRITEMASK,
D3DRENDERSTATE_TEXTUREFACTOR,
D3DRENDERSTATE_WRAP0,
D3DRENDERSTATE_WRAP1,
D3DRENDERSTATE_WRAP2,
D3DRENDERSTATE_WRAP3,
D3DRENDERSTATE_WRAP4,
D3DRENDERSTATE_WRAP5,
D3DRENDERSTATE_WRAP6,
D3DRENDERSTATE_WRAP7,
D3DRS_COLORWRITEENABLE,
D3DRS_BLENDOP,
};
static D3DTEXTURESTAGESTATETYPE tsstates[] =
{
D3DTSS_COLOROP,
D3DTSS_COLORARG1,
D3DTSS_COLORARG2,
D3DTSS_ALPHAOP,
D3DTSS_ALPHAARG1,
D3DTSS_ALPHAARG2,
D3DTSS_BUMPENVMAT00,
D3DTSS_BUMPENVMAT01,
D3DTSS_BUMPENVMAT10,
D3DTSS_BUMPENVMAT11,
D3DTSS_TEXCOORDINDEX,
D3DTSS_ADDRESSU,
D3DTSS_ADDRESSV,
D3DTSS_BORDERCOLOR,
D3DTSS_MAGFILTER,
D3DTSS_MINFILTER,
D3DTSS_MIPFILTER,
D3DTSS_MIPMAPLODBIAS,
D3DTSS_MAXMIPLEVEL,
D3DTSS_MAXANISOTROPY,
D3DTSS_BUMPENVLSCALE,
D3DTSS_BUMPENVLOFFSET,
D3DTSS_TEXTURETRANSFORMFLAGS,
D3DTSS_ADDRESSW,
D3DTSS_COLORARG0,
D3DTSS_ALPHAARG0,
D3DTSS_RESULTARG,
};
//
// Capture render-states
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2RENDERSTATE) *
sizeof(rstates)/sizeof(D3DRENDERSTATETYPE);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = sizeof(rstates)/sizeof(D3DRENDERSTATETYPE);
pCmd->bCommand = D3DDP2OP_RENDERSTATE;
D3DHAL_DP2RENDERSTATE* pRS = (D3DHAL_DP2RENDERSTATE*)(pCmd + 1);
for( i = 0; i < sizeof(rstates)/sizeof(D3DRENDERSTATETYPE); ++i)
{
pRS->RenderState = rstates[i];
pRS->dwState = GetRS()[rstates[i]];
pRS++;
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture texture-stage-states
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2TEXTURESTAGESTATE)
* sizeof(tsstates)/sizeof(D3DTEXTURESTAGESTATETYPE)
* D3DHAL_TSS_MAXSTAGES;
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = sizeof(tsstates)/sizeof(D3DTEXTURESTAGESTATETYPE)
* D3DHAL_TSS_MAXSTAGES;
pCmd->bCommand = D3DDP2OP_TEXTURESTAGESTATE;
D3DHAL_DP2TEXTURESTAGESTATE* pTSS = (D3DHAL_DP2TEXTURESTAGESTATE*)(pCmd+1);
for ( i = 0; i < D3DHAL_TSS_MAXSTAGES; i++ )
{
for( DWORD j = 0; j < sizeof(tsstates)/
sizeof(D3DTEXTURESTAGESTATETYPE); ++j)
{
pTSS->wStage = i;
pTSS->TSState = tsstates[j];
pTSS->dwValue = GetTSS( i )[tsstates[j]];
pTSS++;
}
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture pixel shader constants
//
data_size = sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2SETPIXELSHADERCONST) + (RDPS_MAX_NUMCONSTREG << 4);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETPIXELSHADERCONST;
D3DHAL_DP2SETPIXELSHADERCONST* pPSC =
(D3DHAL_DP2SETPIXELSHADERCONST*)(pCmd+1);
pPSC->dwRegister = 0;
pPSC->dwCount = RDPS_MAX_NUMCONSTREG;
FLOAT* pfData = (FLOAT*)(pPSC+1);
for (UINT iR=pPSC->dwRegister; iR<pPSC->dwCount; iR++)
{
*(pfData+0) = m_Rast.m_ConstReg[iR][0][0];
*(pfData+1) = m_Rast.m_ConstReg[iR][0][1];
*(pfData+2) = m_Rast.m_ConstReg[iR][0][2];
*(pfData+3) = m_Rast.m_ConstReg[iR][0][3];
pfData += 4;
}
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
//
// Capture current pixel shader
//
data_size = sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2PIXELSHADER);
HR_RET(data.Grow( data_size ));
pCmd = (LPD3DHAL_DP2COMMAND)&(data[0]);
pCmd->wPrimitiveCount = 1;
pCmd->bCommand = D3DDP2OP_SETPIXELSHADER;
D3DHAL_DP2PIXELSHADER* pPS = (D3DHAL_DP2PIXELSHADER*)(pCmd+1);
pPS->dwHandle = m_CurrentPShaderHandle;
HR_RET(RecordStates( (PUINT8)pCmd, data_size ));
return hr;
}
//-----------------------------------------------------------------------------
//
// SetRenderState -
//
//-----------------------------------------------------------------------------
void
RefDev::SetRenderState( DWORD dwState, DWORD dwValue )
{
// check for range before continuing
if( dwState >= D3DHAL_MAX_RSTATES )
{
return;
}
// set value in internal object
m_dwRenderState[dwState] = dwValue;
if( m_pDbgMon ) m_pDbgMon->StateChanged( D3DDM_SC_DEVICESTATE );
// do special validation work for some render states
switch ( dwState )
{
case D3DRS_DEBUGMONITORTOKEN:
if( m_pDbgMon ) m_pDbgMon->NextEvent( D3DDM_EVENT_RSTOKEN );
break;
case D3DRENDERSTATE_ZENABLE:
if( dwValue )
m_Clipper.m_dwFlags |= RefClipper::RCLIP_Z_ENABLE;
else
m_Clipper.m_dwFlags &= ~RefClipper::RCLIP_Z_ENABLE;
break;
case D3DRENDERSTATE_LIGHTING:
if( dwValue )
m_RefVP.m_dwTLState |= RDPV_DOLIGHTING;
else
m_RefVP.m_dwTLState &= ~RDPV_DOLIGHTING;
break;
case D3DRS_INDEXEDVERTEXBLENDENABLE:
if( dwValue )
m_RefVP.m_dwTLState |= RDPV_DOINDEXEDVERTEXBLEND;
else
m_RefVP.m_dwTLState &= ~RDPV_DOINDEXEDVERTEXBLEND;
break;
case D3DRENDERSTATE_CLIPPING:
if( dwValue )
m_RefVP.m_dwTLState |= RDPV_DOCLIPPING;
else
m_RefVP.m_dwTLState &= ~RDPV_DOCLIPPING;
break;
case D3DRENDERSTATE_SHADEMODE:
{
if( dwValue == D3DSHADE_FLAT )
m_Clipper.m_dwFlags |= RefClipper::RCLIP_DO_FLATSHADING;
else
m_Clipper.m_dwFlags &= ~RefClipper::RCLIP_DO_FLATSHADING;
}
break;
case D3DRENDERSTATE_FILLMODE:
{
if( dwValue == D3DFILL_WIREFRAME )
m_Clipper.m_dwFlags |= RefClipper::RCLIP_DO_WIREFRAME;
else
m_Clipper.m_dwFlags &= ~RefClipper::RCLIP_DO_WIREFRAME;
}
break;
case D3DRENDERSTATE_NORMALIZENORMALS:
{
if( dwValue )
m_RefVP.m_dwTLState |= RDPV_NORMALIZENORMALS;
else
m_RefVP.m_dwTLState &= ~RDPV_NORMALIZENORMALS;
}
break;
case D3DRENDERSTATE_LOCALVIEWER:
{
if( dwValue )
m_RefVP.m_dwTLState |= RDPV_LOCALVIEWER;
else
m_RefVP.m_dwTLState &= ~RDPV_LOCALVIEWER;
}
break;
case D3DRENDERSTATE_SPECULARENABLE:
{
if( dwValue )
m_RefVP.m_dwTLState |= RDPV_DOSPECULAR;
else
m_RefVP.m_dwTLState &= ~RDPV_DOSPECULAR;
}
break;
case D3DRENDERSTATE_COLORVERTEX:
case D3DRENDERSTATE_AMBIENTMATERIALSOURCE:
case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE:
case D3DRENDERSTATE_SPECULARMATERIALSOURCE:
case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE:
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_COLORVTX;
break;
case D3DRENDERSTATE_FOGCOLOR:
{
m_RefVP.m_lighting.fog_color = (D3DCOLOR) dwValue;
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_FOG;
}
break;
case D3DRENDERSTATE_FOGTABLESTART:
{
m_RefVP.m_lighting.fog_start = *(D3DVALUE*)&dwValue;
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_FOG;
}
break;
case D3DRENDERSTATE_FOGTABLEEND:
{
m_RefVP.m_lighting.fog_end = *(D3DVALUE*)&dwValue;
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_FOG;
}
break;
case D3DRENDERSTATE_FOGTABLEDENSITY:
{
m_RefVP.m_lighting.fog_density = *(D3DVALUE*)&dwValue;
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_FOG;
}
break;
case D3DRENDERSTATE_FOGVERTEXMODE:
{
m_RefVP.m_lighting.fog_mode = (int) dwValue;
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_FOG;
}
break;
case D3DRENDERSTATE_AMBIENT:
{
m_RefVP.m_lighting.ambient_red =
D3DVAL(RGBA_GETRED(dwValue))/D3DVALUE(255);
m_RefVP.m_lighting.ambient_green =
D3DVAL(RGBA_GETGREEN(dwValue))/D3DVALUE(255);
m_RefVP.m_lighting.ambient_blue =
D3DVAL(RGBA_GETBLUE(dwValue))/D3DVALUE(255);
m_RefVP.m_lighting.ambient_save = dwValue;
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_MATERIAL;
}
break;
//
// map legacy texture to multi-texture stage 0
//
case D3DRENDERSTATE_TEXTUREMAPBLEND:
// map legacy blending state to texture stage 0
MapLegacyTextureBlend();
break;
// map legacy modes with one-to-one mappings to texture stage 0
case D3DRENDERSTATE_TEXTUREADDRESS:
// not available in DX8 headers
// m_TextureStageState[0].m_dwVal[D3DTSS_ADDRESS] =
m_TextureStageState[0].m_dwVal[D3DTSS_ADDRESSU] =
m_TextureStageState[0].m_dwVal[D3DTSS_ADDRESSV] = dwValue;
break;
case D3DRENDERSTATE_TEXTUREADDRESSU:
m_TextureStageState[0].m_dwVal[D3DTSS_ADDRESSU] = dwValue;
break;
case D3DRENDERSTATE_TEXTUREADDRESSV:
m_TextureStageState[0].m_dwVal[D3DTSS_ADDRESSV] = dwValue;
break;
case D3DRENDERSTATE_MIPMAPLODBIAS:
m_TextureStageState[0].m_dwVal[D3DTSS_MIPMAPLODBIAS] = dwValue;
break;
case D3DRENDERSTATE_BORDERCOLOR:
m_TextureStageState[0].m_dwVal[D3DTSS_BORDERCOLOR] = dwValue;
break;
case D3DRENDERSTATE_ANISOTROPY:
m_TextureStageState[0].m_dwVal[D3DTSS_MAXANISOTROPY] = dwValue;
// fall thru to update filter state
case D3DRENDERSTATE_TEXTUREMAG:
case D3DRENDERSTATE_TEXTUREMIN:
// map legacy filtering/sampling state to texture stage 0
MapLegacyTextureFilter();
break;
case D3DRENDERSTATE_TEXTUREHANDLE:
// map thru to set handle for first stage
SetTextureStageState( 0, D3DTSS_TEXTUREMAP, dwValue );
break;
//
// map legacy WRAPU/V state through to controls for tex coord 0
//
case D3DRENDERSTATE_WRAPU:
m_dwRenderState[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
m_dwRenderState[D3DRENDERSTATE_WRAP0] |= ((dwValue) ? D3DWRAP_U : 0);
break;
case D3DRENDERSTATE_WRAPV:
m_dwRenderState[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
m_dwRenderState[D3DRENDERSTATE_WRAP0] |= ((dwValue) ? D3DWRAP_V : 0);
break;
case D3DRS_MULTISAMPLEANTIALIAS:
case D3DRS_MULTISAMPLEMASK:
m_dwRastFlags |= RDRF_MULTISAMPLE_CHANGED;
break;
//
// Scene Capture
//
case D3DRENDERSTATE_SCENECAPTURE:
if( dwValue )
SceneCapture(D3DHAL_SCENE_CAPTURE_START);
else
SceneCapture(D3DHAL_SCENE_CAPTURE_END);
break;
case D3DRS_POINTSIZE:
m_RefVP.m_fPointSize = m_fRenderState[dwState];
break;
case D3DRS_POINTSCALE_A:
m_RefVP.m_fPointAttA = m_fRenderState[dwState];
break;
case D3DRS_POINTSCALE_B:
m_RefVP.m_fPointAttB = m_fRenderState[dwState];
break;
case D3DRS_POINTSCALE_C:
m_RefVP.m_fPointAttC = m_fRenderState[dwState];
break;
case D3DRS_POINTSIZE_MIN:
m_RefVP.m_fPointSizeMin = m_fRenderState[dwState];
break;
case D3DRS_POINTSIZE_MAX:
m_RefVP.m_fPointSizeMax = min(RD_MAX_POINT_SIZE,
m_fRenderState[dwState]);
break;
case D3DRS_TWEENFACTOR:
m_RefVP.m_fTweenFactor = m_fRenderState[dwState];
break;
//
// HOSurface DDI only renderstate
//
case D3DRS_DELETERTPATCH:
if(dwValue < m_HOSCoeffs.GetSize())
{
RDHOCoeffs &coeffs = m_HOSCoeffs[dwValue];
delete[] coeffs.m_pNumSegs;
coeffs.m_pNumSegs = 0;
for(unsigned i = 0; i < RD_MAX_NUMSTREAMS; ++i)
{
delete[] coeffs.m_pData[i];
coeffs.m_pData[i] = 0;
}
}
}
}
HRESULT
RefDev::Dp2SetRenderTarget(LPD3DHAL_DP2COMMAND pCmd)
{
LPD3DHAL_DP2SETRENDERTARGET pSRTData;
HRESULT hr;
// Get new data by ignoring all but the last structure
pSRTData = (D3DHAL_DP2SETRENDERTARGET*)(pCmd + 1) + (pCmd->wStateCount - 1);
// set 'changed' flags
m_dwRastFlags =
RDRF_MULTISAMPLE_CHANGED|
RDRF_PIXELSHADER_CHANGED|
RDRF_LEGACYPIXELSHADER_CHANGED|
RDRF_TEXTURESTAGESTATE_CHANGED;
return GetRenderTarget()->Initialize( m_pDDLcl,
pSRTData->hRenderTarget,
pSRTData->hZBuffer );
}
HRESULT
RefDev::Dp2CreateVertexShader( DWORD handle,
DWORD dwDeclSize, LPDWORD pDecl,
DWORD dwCodeSize, LPDWORD pCode )
{
HRESULT hr = S_OK;
HR_RET( m_VShaderHandleArray.Grow( handle ) );
//
// Validation sequence
//
#if DBG
_ASSERT( m_VShaderHandleArray[handle].m_tag == 0,
"A shader exists with the given handle, tag is non-zero" );
#endif
_ASSERT( pDecl, "A declaration should exist" );
_ASSERT( dwDeclSize, "A declaration size should be non-zero" );
_ASSERT( m_VShaderHandleArray[handle].m_pShader == NULL,
"A shader exists with the given handle" );
RDVShader* pShader = m_VShaderHandleArray[handle].m_pShader =
new RDVShader;
if( pShader == NULL )
return E_OUTOFMEMORY;
//
// Parse the declaration
//
if( FAILED( hr = pShader->m_Declaration.Parse( pDecl,
!(BOOL)dwCodeSize ) ) )
{
DPFERR( "Vertex Shader declaration parsing failed" );
goto error_ret;
}
//
// Now compile the shader code if any of it is given
//
if( dwCodeSize )
{
pShader->m_pCode = m_RefVM.CompileCode( dwCodeSize, pCode );
if( pShader->m_pCode == NULL )
{
DPFERR( "Vertex Shader Code compilation failed" );
hr = E_FAIL;
goto error_ret;
}
}
#if DBG
// Everything successful, mark this handle as in use.
m_VShaderHandleArray[handle].m_tag = 1;
#endif
if( m_pDbgMon ) m_pDbgMon->StateChanged( D3DDM_SC_VSMODIFYSHADERS );
return S_OK;
error_ret:
delete pShader;
m_VShaderHandleArray[handle].m_pShader = NULL;
#if DBG
m_VShaderHandleArray[handle].m_tag = 0;
#endif
return hr;
}
HRESULT
RefDev::Dp2DeleteVertexShader(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
LPD3DHAL_DP2VERTEXSHADER pVS =
(LPD3DHAL_DP2VERTEXSHADER)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
DWORD handle = pVS[i].dwHandle;
_ASSERT( m_VShaderHandleArray.IsValidIndex( handle ),
"Such a shader does not exist" );
_ASSERT( m_VShaderHandleArray[handle].m_pShader,
"Such a shader does not exist" );
delete m_VShaderHandleArray[handle].m_pShader;
m_VShaderHandleArray[handle].m_pShader = NULL;
#if DBG
m_VShaderHandleArray[handle].m_tag = 0;
#endif
if( handle == m_CurrentVShaderHandle )
{
m_CurrentVShaderHandle = 0;
m_pCurrentVShader = NULL;
}
}
if( m_pDbgMon ) m_pDbgMon->StateChanged( D3DDM_SC_VSMODIFYSHADERS );
return hr;
}
HRESULT
RefDev::Dp2SetVertexShader(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
LPD3DHAL_DP2VERTEXSHADER pVS =
(LPD3DHAL_DP2VERTEXSHADER)(pCmd + 1);
// Just set the last Vertex Shader in this array
DWORD handle = pVS[pCmd->wStateCount-1].dwHandle;
//
// Zero is a special handle that tells the driver to
// invalidate the currently set shader.
//
if( handle == 0 )
{
m_pCurrentVShader = NULL;
m_CurrentVShaderHandle = handle;
return hr;
}
if( RDVSD_ISLEGACY(handle) )
{
// Make it parse the FVF and build the VertexElement array
hr = m_FVFShader.m_Declaration.MakeVElementArray( handle );
if( FAILED( hr ) )
{
DPFERR( "MakeVElementArray failed" );
return hr;
}
m_pCurrentVShader = &m_FVFShader;
}
else
{
if( !m_VShaderHandleArray.IsValidIndex( handle ) ||
(m_VShaderHandleArray[handle].m_pShader == NULL) )
{
DPFERR( "Such a Vertex Shader has not been created" );
return E_INVALIDARG;
}
m_pCurrentVShader = m_VShaderHandleArray[handle].m_pShader;
// Save the tesselator stride computed at parsing time.
// This feature is only available when using a Declaration.
m_VStream[RDVSD_STREAMTESS].m_dwStride =
m_pCurrentVShader->m_Declaration.m_dwStreamTessStride;
}
if( m_pCurrentVShader->m_pCode )
{
hr = m_RefVM.SetActiveShaderCode( m_pCurrentVShader->m_pCode );
if( FAILED( hr ) )
{
DPFERR( "SetActiveShaderCode failed" );
return hr;
}
RDVConstantData* pConst =
m_pCurrentVShader->m_Declaration.m_pConstants;
while( pConst )
{
hr = m_RefVM.SetData( D3DSPR_CONST,
pConst->m_dwAddress,
pConst->m_dwCount,
pConst->m_pData );
if( FAILED( hr ) )
{
DPFERR( "SetVMData failed" );
return hr;
}
pConst = static_cast<RDVConstantData *>(pConst->m_pNext);
}
}
m_CurrentVShaderHandle = handle;
if( m_pCurrentVShader->m_Declaration.m_qwInputFVF != m_RefVP.m_qwFVFIn )
{
m_RefVP.m_dwDirtyFlags |= RDPV_DIRTY_COLORVTX;
}
m_RefVP.m_qwFVFIn = m_pCurrentVShader->m_Declaration.m_qwInputFVF;
if( m_pDbgMon ) m_pDbgMon->StateChanged( D3DDM_SC_VSSETSHADER );
return hr;
}
HRESULT
RefDev::Dp2SetVertexShaderConsts( DWORD StartReg, DWORD dwCount,
LPDWORD pData )
{
HRESULT hr = m_RefVM.SetData( D3DSPR_CONST, StartReg, dwCount, pData );
if( m_pDbgMon ) m_pDbgMon->StateChanged( D3DDM_SC_VSCONSTANTS );
return hr;
}
HRESULT
RefDev::Dp2SetStreamSource(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
LPD3DHAL_DP2SETSTREAMSOURCE pSSS =
(LPD3DHAL_DP2SETSTREAMSOURCE)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
RDVStream& Stream = m_VStream[pSSS[i].dwStream];
// NULL handle means that the StreamSource should be unset.
if( pSSS[i].dwVBHandle == 0 )
{
Stream.m_pData = NULL;
Stream.m_dwStride = 0;
Stream.m_dwHandle = 0;
}
else
{
// Check if the handle has a valid vertexbuffer
RDSurface* pSurf =
g_SurfMgr.GetSurfFromList(m_pDDLcl, pSSS[i].dwVBHandle);
if( (pSurf == NULL) ||
(pSurf->GetSurfaceType() != RR_ST_VERTEXBUFFER) )
{
DPFERR( "Invalid VB Handle passed in SetStreamSource" );
return E_INVALIDARG;
}
RDVertexBuffer* pVB = static_cast<RDVertexBuffer *>(pSurf);
Stream.m_pData = pVB->GetBits();
Stream.m_dwStride = pSSS[i].dwStride;
Stream.m_dwHandle = pSSS[i].dwVBHandle;
}
}
return hr;
}
HRESULT
RefDev::Dp2SetStreamSourceUM( LPD3DHAL_DP2COMMAND pCmd,
PUINT8 pUMVtx )
{
HRESULT hr = S_OK;
// Get new data by ignoring all but the last structure
D3DHAL_DP2SETSTREAMSOURCEUM* pSSUM =
(D3DHAL_DP2SETSTREAMSOURCEUM*)(pCmd + 1) + (pCmd->wStateCount - 1);
// Access only the Zero'th stream
m_VStream[pSSUM->dwStream].m_pData = pUMVtx;
m_VStream[pSSUM->dwStream].m_dwStride = pSSUM->dwStride;
m_VStream[pSSUM->dwStream].m_dwHandle = 0;
return hr;
}
HRESULT
RefDev::Dp2SetIndices(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
// Get new data by ignoring all but the last structure
D3DHAL_DP2SETINDICES* pSI =
(D3DHAL_DP2SETINDICES*)(pCmd + 1) + (pCmd->wStateCount - 1);
// NULL handle means that the StreamSource should be unset.
if( pSI->dwVBHandle == 0 )
{
m_IndexStream.m_pData = NULL;
m_IndexStream.m_dwStride = 0;
m_IndexStream.m_dwHandle = 0;
}
else
{
// Check if the handle has a valid vertexbuffer
RDSurface* pSurf = g_SurfMgr.GetSurfFromList(m_pDDLcl,
pSI->dwVBHandle);
if( (pSurf == NULL) ||
(pSurf->GetSurfaceType() != RR_ST_VERTEXBUFFER) )
{
DPFERR( "Invalid VB Handle passed in SetIndices" );
return E_INVALIDARG;
}
RDVertexBuffer* pVB = static_cast<RDVertexBuffer *>(pSurf);
m_IndexStream.m_pData = pVB->GetBits();
m_IndexStream.m_dwStride = pSI->dwStride;
m_IndexStream.m_dwHandle = pSI->dwVBHandle;
}
return hr;
}
HRESULT
RefDev::Dp2DrawPrimitive(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
//
// Validation
//
_ASSERT( m_CurrentVShaderHandle, "No vertex shader currently bound" );
LPD3DHAL_DP2DRAWPRIMITIVE pDP = (LPD3DHAL_DP2DRAWPRIMITIVE)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
if( FAILED( hr = DrawDX8Prim( &(pDP[i]) ) ) )
return hr;
}
return hr;
}
HRESULT
RefDev::Dp2DrawPrimitive2(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
//
// Validation
//
_ASSERT( m_CurrentVShaderHandle, "No vertex shader currently bound" );
LPD3DHAL_DP2DRAWPRIMITIVE2 pDP = (LPD3DHAL_DP2DRAWPRIMITIVE2)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
if( FAILED( hr = DrawDX8Prim2( &(pDP[i]) ) ) )
return hr;
}
return hr;
}
HRESULT
RefDev::Dp2DrawIndexedPrimitive(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
//
// Validation
//
_ASSERT( m_CurrentVShaderHandle, "No vertex shader currently bound" );
LPD3DHAL_DP2DRAWINDEXEDPRIMITIVE pDIP =
(LPD3DHAL_DP2DRAWINDEXEDPRIMITIVE)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
if( FAILED( hr = DrawDX8IndexedPrim( &(pDIP[i]) ) ) )
return hr;
}
return hr;
}
HRESULT
RefDev::Dp2DrawIndexedPrimitive2(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
//
// Validation
//
_ASSERT( m_CurrentVShaderHandle, "No vertex shader currently bound" );
LPD3DHAL_DP2DRAWINDEXEDPRIMITIVE2 pDIP =
(LPD3DHAL_DP2DRAWINDEXEDPRIMITIVE2)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
if( FAILED( hr = DrawDX8IndexedPrim2( &(pDIP[i]) ) ) )
return hr;
}
return hr;
}
HRESULT
RefDev::Dp2DrawClippedTriFan(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
//
// Validation
//
_ASSERT( m_CurrentVShaderHandle, "No vertex shader currently bound" );
LPD3DHAL_CLIPPEDTRIANGLEFAN pDIP =
(LPD3DHAL_CLIPPEDTRIANGLEFAN)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
if( FAILED( hr = DrawDX8ClippedTriFan( &(pDIP[i]) ) ) )
return hr;
}
return hr;
}
HRESULT
RefDev::Dp2SetPalette(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
LPD3DHAL_DP2SETPALETTE pSP = (LPD3DHAL_DP2SETPALETTE)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
HR_RET( m_PaletteHandleArray.Grow( pSP->dwPaletteHandle ) );
if( m_PaletteHandleArray[pSP->dwPaletteHandle].m_pPal == NULL )
{
m_PaletteHandleArray[pSP->dwPaletteHandle].m_pPal = new RDPalette;
}
RDPalette* pPal = m_PaletteHandleArray[pSP->dwPaletteHandle].m_pPal;
pPal->m_dwFlags = (pSP->dwPaletteFlags & DDRAWIPAL_ALPHA) ?
RDPalette::RDPAL_ALPHAINPALETTE : 0;
RDSurface2D* pSurf = (RDSurface2D *)g_SurfMgr.GetSurfFromList(
m_pDDLcl, pSP->dwSurfaceHandle );
if( pSurf == NULL ) return E_FAIL;
if( (pSurf->GetSurfaceType() & RR_ST_TEXTURE) == 0 )
{
DPFERR( "Setting palette to a non-texture\n" );
return E_FAIL;
}
pSurf->SetPalette( pPal );
}
return hr;
}
HRESULT
RefDev::Dp2UpdatePalette(LPD3DHAL_DP2UPDATEPALETTE pUP, PALETTEENTRY* pPalData)
{
HRESULT hr = S_OK;
HR_RET( m_PaletteHandleArray.Grow( pUP->dwPaletteHandle ) );
if( m_PaletteHandleArray[pUP->dwPaletteHandle].m_pPal == NULL )
{
m_PaletteHandleArray[pUP->dwPaletteHandle].m_pPal = new RDPalette;
}
RDPalette* pPal = m_PaletteHandleArray[pUP->dwPaletteHandle].m_pPal;
HR_RET( pPal->Update( pUP->wStartIndex, pUP->wNumEntries, pPalData ) );
return hr;
}
HRESULT
RefDev::Dp2SetTexLod(LPD3DHAL_DP2COMMAND pCmd)
{
HRESULT hr = S_OK;
LPD3DHAL_DP2SETTEXLOD pSTL = (LPD3DHAL_DP2SETTEXLOD)(pCmd + 1);
for( int i = 0; i < pCmd->wStateCount; i++ )
{
RDSurface2D* pSurf = (RDSurface2D *)g_SurfMgr.GetSurfFromList(
m_pDDLcl, pSTL->dwDDSurface );
if( pSurf == NULL ) return E_FAIL;
if( (pSurf->GetSurfaceType() & RR_ST_TEXTURE) == 0 )
{
DPFERR( "Setting LOD to a non-texture\n" );
return E_FAIL;
}
HR_RET(pSurf->SetLod( pSTL->dwLOD ));
}
return hr;
}