windows-nt/Source/XPSP1/NT/multimedia/directx/dxg/d3d8/fe/stateset.cpp

2256 lines
86 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*==========================================================================;
*
* Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
*
* File: stateset.cpp
* Content: State sets handling
*
***************************************************************************/
#include "pch.cpp"
#pragma hdrstop
#include "fe.h"
//=====================================================================
// CStateSets interface
//
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::CStateSets"
CStateSets::CStateSets(): m_SetHandles(10), m_DeviceHandles(10), m_GrowSize(10)
{
m_dwMaxSets = 0;
m_dwCurrentHandle = __INVALIDHANDLE;
m_pStateSets = NULL;
// Init handle factory
// m_SetHandles.Init(m_GrowSize, m_GrowSize);
m_SetHandles.CreateNewHandle( NULL ); // Reserve handle 0
// m_DeviceHandles.Init(m_GrowSize, m_GrowSize);
m_DeviceHandles.CreateNewHandle( NULL ); // Reserve handle 0
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::~CStateSets"
CStateSets::~CStateSets()
{
delete m_pBufferSet;
delete [] m_pStateSets;
m_SetHandles.ReleaseHandle(0);
m_DeviceHandles.ReleaseHandle(0);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::Init"
HRESULT CStateSets::Init(CD3DBase *pDev)
{
m_bPure = (pDev->BehaviorFlags() & D3DCREATE_PUREDEVICE) != 0;
m_bTLHal = (pDev->GetDDIType() == D3DDDITYPE_DX7TL) || (pDev->GetDDIType() == D3DDDITYPE_DX8TL);
m_bDX8Dev = (pDev->GetDDIType() >= D3DDDITYPE_DX8);
m_bHardwareVP = (pDev->BehaviorFlags() &
D3DCREATE_HARDWARE_VERTEXPROCESSING);
if(pDev->GetDDIType() > D3DDDITYPE_DX7TL)
{
DWORD value = 0;
GetD3DRegValue(REG_DWORD, "EmulateStateBlocks", &value, sizeof(DWORD));
if(value == 0)
{
m_bEmulate = FALSE;
}
else
{
m_bEmulate = TRUE;
}
}
else
{
m_bEmulate = TRUE;
}
if(m_bPure)
{
m_pBufferSet = new CPureStateSet;
}
else
{
m_pBufferSet = new CStateSet;
}
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::StartNewSet"
HRESULT CStateSets::StartNewSet()
{
m_dwCurrentHandle = m_SetHandles.CreateNewHandle( NULL );
if (m_dwCurrentHandle == __INVALIDHANDLE)
return E_OUTOFMEMORY;
if (m_dwCurrentHandle >= m_dwMaxSets)
{
// Time to grow the array
CStateSet *pNew;
if(m_bPure)
{
pNew = new CPureStateSet[m_dwMaxSets + m_GrowSize];
}
else
{
pNew = new CStateSet[m_dwMaxSets + m_GrowSize];
}
if (pNew == NULL)
{
m_SetHandles.ReleaseHandle(m_dwCurrentHandle);
return E_OUTOFMEMORY;
}
for (DWORD i=0; i < m_dwMaxSets; i++)
pNew[i] = m_pStateSets[i];
delete [] m_pStateSets;
m_pStateSets = pNew;
m_dwMaxSets += m_GrowSize;
}
m_pBufferSet->m_FEOnlyBuffer.Reset();
m_pBufferSet->m_DriverBuffer.Reset();
m_pCurrentStateSet = m_pBufferSet;
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::EndSet"
void CStateSets::EndSet()
{
m_pStateSets[m_dwCurrentHandle] = *m_pCurrentStateSet;
m_pCurrentStateSet = &m_pStateSets[m_dwCurrentHandle];
m_pCurrentStateSet->m_dwStateSetFlags |= __STATESET_INITIALIZED;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::DeleteStateSet"
void CStateSets::DeleteStateSet(CD3DBase *pDevI, DWORD dwHandle)
{
if (dwHandle >= m_dwMaxSets)
{
D3D_ERR("State block handle is greater than available number of blocks");
throw D3DERR_INVALIDCALL;
}
CStateSet *pStateSet = &m_pStateSets[dwHandle];
if (!(pStateSet->m_dwStateSetFlags & __STATESET_INITIALIZED))
{
D3D_ERR("State block is not initialized");
throw D3DERR_INVALIDCALL;
}
// Pass delete instruction to the driver only if there was some data recorded
if (pStateSet->m_dwDeviceHandle != __INVALIDHANDLE)
pDevI->m_pDDI->InsertStateSetOp(D3DHAL_STATESETDELETE,
pStateSet->m_dwDeviceHandle,
(D3DSTATEBLOCKTYPE)0);
Cleanup(dwHandle);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::Cleanup"
void CStateSets::Cleanup(DWORD dwHandle)
{
CStateSet &pStateSet = m_pStateSets[dwHandle];
m_SetHandles.ReleaseHandle(dwHandle);
if (pStateSet.m_dwDeviceHandle != __INVALIDHANDLE)
m_DeviceHandles.ReleaseHandle(pStateSet.m_dwDeviceHandle);
pStateSet.Release();
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::Capture"
void CStateSets::Capture(CD3DBase *pDevI, DWORD dwHandle)
{
if (dwHandle >= m_dwMaxSets)
{
D3D_ERR("Invalid state block handle");
throw D3DERR_INVALIDCALL;
}
CStateSet *pStateSet = &m_pStateSets[dwHandle];
if (!(pStateSet->m_dwStateSetFlags & __STATESET_INITIALIZED))
{
D3D_ERR("State block not initialized");
throw D3DERR_INVALIDCALL;
}
pStateSet->Capture(pDevI, TRUE);
if (pStateSet->m_dwDeviceHandle != __INVALIDHANDLE)
{
pStateSet->Capture(pDevI, FALSE);
pDevI->m_pDDI->InsertStateSetOp(D3DHAL_STATESETCAPTURE,
pStateSet->m_dwDeviceHandle,
(D3DSTATEBLOCKTYPE)0);
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::CreatePredefined"
void CStateSets::CreatePredefined(CD3DBase *pDevI, D3DSTATEBLOCKTYPE sbt)
{
if (StartNewSet() != D3D_OK)
throw E_OUTOFMEMORY;
m_pCurrentStateSet->CreatePredefined(pDevI, sbt);
}
//---------------------------------------------------------------------
// Allocates device handle if necessary
// And returns information of the device buffer
//
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::GetDeviceBufferInfo"
void CStateSets::GetDeviceBufferInfo(DWORD* dwStateSetHandle,
LPVOID *pBuffer,
DWORD* dwBufferSize)
{
if (m_pCurrentStateSet->m_DriverBuffer.m_dwCurrentSize != 0)
{
// Allocate a handle for the device
m_pCurrentStateSet->m_dwDeviceHandle = m_DeviceHandles.CreateNewHandle( NULL );
if (m_pCurrentStateSet->m_dwDeviceHandle == __INVALIDHANDLE)
{
D3D_ERR("Cannot allocate device handle for a state block");
throw E_OUTOFMEMORY;
}
}
*dwStateSetHandle = m_pCurrentStateSet->m_dwDeviceHandle;
*pBuffer = (LPVOID)m_pCurrentStateSet->m_DriverBuffer.m_pBuffer;
*dwBufferSize = m_pCurrentStateSet->m_DriverBuffer.m_dwCurrentSize;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::GetDeviceBufferInfo"
void CStateSets::CreateNewDeviceHandle(DWORD* dwStateSetHandle)
{
// Allocate a handle for the device
m_pCurrentStateSet->m_dwDeviceHandle = m_DeviceHandles.CreateNewHandle( NULL );
if (m_pCurrentStateSet->m_dwDeviceHandle == __INVALIDHANDLE)
{
D3D_ERR("Cannot allocate device handle for a state block");
throw E_OUTOFMEMORY;
}
*dwStateSetHandle = m_pCurrentStateSet->m_dwDeviceHandle;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSet::TranslateDeviceBufferToDX7DDI"
void CStateSets::TranslateDeviceBufferToDX7DDI( DWORD* p, DWORD dwSize )
{
DWORD* pEnd = (DWORD*)((BYTE*)p + dwSize);
while (p < pEnd)
{
LPD3DHAL_DP2COMMAND pCommand = (LPD3DHAL_DP2COMMAND)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
switch ((D3DHAL_DP2OPERATION)pCommand->bCommand)
{
case D3DDP2OP_RENDERSTATE:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
D3DRENDERSTATETYPE dwState = (D3DRENDERSTATETYPE)*p++;
DWORD dwValue = *p++;
}
}
break;
case D3DDP2OP_SETLIGHT:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETLIGHT pData = (LPD3DHAL_DP2SETLIGHT)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETLIGHT));
switch (pData->dwDataType)
{
case D3DHAL_SETLIGHT_ENABLE:
case D3DHAL_SETLIGHT_DISABLE:
break;
case D3DHAL_SETLIGHT_DATA:
p = (LPDWORD)((LPBYTE)p + sizeof(D3DLIGHT8));
break;
}
}
break;
}
case D3DDP2OP_SETMATERIAL:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETMATERIAL));
}
break;
}
case D3DDP2OP_SETTRANSFORM:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETTRANSFORM));
}
break;
}
case D3DDP2OP_TEXTURESTAGESTATE:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2TEXTURESTAGESTATE pData = (LPD3DHAL_DP2TEXTURESTAGESTATE)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2TEXTURESTAGESTATE));
// Map DX8 filter enums to DX6/7 enums
switch (pData->TSState)
{
case D3DTSS_MAGFILTER: pData->dwValue = texf2texfg[min(D3DTEXF_GAUSSIANCUBIC,pData->dwValue)]; break;
case D3DTSS_MINFILTER: pData->dwValue = texf2texfn[min(D3DTEXF_GAUSSIANCUBIC,pData->dwValue)]; break;
case D3DTSS_MIPFILTER: pData->dwValue = texf2texfp[min(D3DTEXF_GAUSSIANCUBIC,pData->dwValue)]; break;
}
}
break;
}
case D3DDP2OP_VIEWPORTINFO:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2VIEWPORTINFO));
// The next command has to be D3DDP2OP_ZRANGE
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2ZRANGE));
}
break;
}
case D3DDP2OP_SETCLIPPLANE:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETCLIPPLANE));
}
break;
}
#ifdef DBG
default:
DXGASSERT(FALSE);
#endif
}
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertRenderState"
void CStateSets::InsertRenderState(D3DRENDERSTATETYPE state, DWORD dwValue,
BOOL bDriverCanHandle)
{
struct
{
D3DRENDERSTATETYPE state;
DWORD dwValue;
} data = {state, dwValue};
m_pCurrentStateSet->InsertCommand(D3DDP2OP_RENDERSTATE,
&data, sizeof(data),
!m_bEmulate && bDriverCanHandle);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertLight"
void CStateSets::InsertLight(DWORD dwLightIndex, CONST D3DLIGHT8* pData)
{
struct
{
D3DHAL_DP2SETLIGHT header;
D3DLIGHT8 light;
} data;
data.header.dwIndex = dwLightIndex;
data.header.dwDataType = D3DHAL_SETLIGHT_DATA;
data.light= *pData;
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETLIGHT, &data, sizeof(data),
!m_bEmulate && m_bTLHal);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertLightEnable"
void CStateSets::InsertLightEnable(DWORD dwLightIndex, BOOL bEnable)
{
D3DHAL_DP2SETLIGHT data;
data.dwIndex = dwLightIndex;
if (bEnable)
data.dwDataType = D3DHAL_SETLIGHT_ENABLE;
else
data.dwDataType = D3DHAL_SETLIGHT_DISABLE;
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETLIGHT, &data, sizeof(data),
!m_bEmulate && m_bTLHal);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertViewport"
void CStateSets::InsertViewport(CONST D3DVIEWPORT8* lpVwpData)
{
D3DHAL_DP2VIEWPORTINFO data2;
data2.dwX = lpVwpData->X;
data2.dwY = lpVwpData->Y;
data2.dwWidth = lpVwpData->Width;
data2.dwHeight = lpVwpData->Height;
m_pCurrentStateSet->InsertCommand(D3DDP2OP_VIEWPORTINFO, &data2, sizeof(data2),
!m_bEmulate && m_bTLHal);
D3DHAL_DP2ZRANGE data1;
data1.dvMinZ = lpVwpData->MinZ;
data1.dvMaxZ = lpVwpData->MaxZ;
m_pCurrentStateSet->InsertCommand(D3DDP2OP_ZRANGE, &data1, sizeof(data1),
!m_bEmulate && m_bTLHal);
m_pCurrentStateSet->ResetCurrentCommand();
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertMaterial"
void CStateSets::InsertMaterial(CONST D3DMATERIAL8* pData)
{
D3DMATERIAL8 mat = *pData;
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETMATERIAL,
&mat,
sizeof(D3DMATERIAL8),
!m_bEmulate && m_bTLHal);
m_pCurrentStateSet->ResetCurrentCommand();
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertClipPlane"
void CStateSets::InsertClipPlane(DWORD dwPlaneIndex,
CONST D3DVALUE* pPlaneEquation)
{
D3DHAL_DP2SETCLIPPLANE data;
data.dwIndex = dwPlaneIndex;
data.plane[0] = pPlaneEquation[0];
data.plane[1] = pPlaneEquation[1];
data.plane[2] = pPlaneEquation[2];
data.plane[3] = pPlaneEquation[3];
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETCLIPPLANE,
&data, sizeof(data),
!m_bEmulate && m_bTLHal);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertTransform"
void CStateSets::InsertTransform(D3DTRANSFORMSTATETYPE state,
CONST D3DMATRIX* lpMat)
{
D3DHAL_DP2SETTRANSFORM data;
data.xfrmType = state;
data.matrix = *lpMat;
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETTRANSFORM,
&data, sizeof(data),
!m_bEmulate && m_bTLHal);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertTextureStageState"
void CStateSets::InsertTextureStageState(DWORD dwStage,
D3DTEXTURESTAGESTATETYPE type,
DWORD dwValue)
{
D3DHAL_DP2TEXTURESTAGESTATE data = {(WORD)dwStage, type, dwValue};
m_pCurrentStateSet->InsertCommand(D3DDP2OP_TEXTURESTAGESTATE,
&data, sizeof(data),
!m_bEmulate);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertTexture"
void CStateSets::InsertTexture(DWORD dwStage, IDirect3DBaseTexture8 *pTex)
{
D3DHAL_DP2FRONTENDDATA data = {(WORD)dwStage, pTex};
// Up the internal refcount of this texture.
CBaseTexture *lpTexI = CBaseTexture::SafeCast(pTex);
if (lpTexI)
lpTexI->IncrementUseCount();
// Only the front-end will parse this instruction
m_pCurrentStateSet->InsertCommand((D3DHAL_DP2OPERATION)D3DDP2OP_FRONTENDDATA, &data, sizeof(data), FALSE);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertCurrentTexturePalette"
void CStateSets::InsertCurrentTexturePalette(DWORD PaletteNumber)
{
D3DHAL_DP2FESETPAL data = {PaletteNumber};
// Only the front-end will parse this instruction
m_pCurrentStateSet->InsertCommand((D3DHAL_DP2OPERATION)D3DDP2OP_FESETPAL, &data, sizeof(data), FALSE);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertVertexShader"
void CStateSets::InsertVertexShader(DWORD dwShaderHandle, BOOL bHardware)
{
D3DHAL_DP2VERTEXSHADER data = {dwShaderHandle};
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETVERTEXSHADER,
&data, sizeof(data),
!m_bEmulate && m_bHardwareVP &&
m_bDX8Dev && bHardware);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertPixelShader"
void CStateSets::InsertPixelShader(DWORD dwShaderHandle)
{
D3DHAL_DP2PIXELSHADER data = {dwShaderHandle};
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETPIXELSHADER,
&data, sizeof(data),
!m_bEmulate && m_bDX8Dev);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertStreamSource"
void CStateSets::InsertStreamSource(DWORD dwStream, CVertexBuffer *pBuf, DWORD dwStride)
{
D3DHAL_DP2FESETVB data = {(WORD)dwStream, pBuf, dwStride};
// Only the front-end will parse this instruction
CVertexBuffer* pVB = static_cast<CVertexBuffer*>(pBuf);
if (pVB)
pVB->IncrementUseCount();
m_pCurrentStateSet->InsertCommand((D3DHAL_DP2OPERATION)D3DDP2OP_FESETVB, &data, sizeof(data), FALSE);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertIndices"
void CStateSets::InsertIndices(CIndexBuffer *pBuf, DWORD dwBaseVertex)
{
D3DHAL_DP2FESETIB data = {pBuf, dwBaseVertex};
// Only the front-end will parse this instruction
CIndexBuffer* pIB = static_cast<CIndexBuffer*>(pBuf);
if (pIB)
pIB->IncrementUseCount();
m_pCurrentStateSet->InsertCommand((D3DHAL_DP2OPERATION)D3DDP2OP_FESETIB, &data, sizeof(data), FALSE);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertVertexShaderConstant"
void CStateSets::InsertVertexShaderConstant(DWORD Register, CONST VOID* pConstantData, DWORD ConstantCount)
{
LPVOID pData = new BYTE[sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) + ConstantCount * 16];
if(pData == 0)
{
throw E_OUTOFMEMORY;
}
((LPD3DHAL_DP2SETVERTEXSHADERCONST)pData)->dwRegister = Register;
((LPD3DHAL_DP2SETVERTEXSHADERCONST)pData)->dwCount = ConstantCount;
memcpy((LPD3DHAL_DP2SETVERTEXSHADERCONST)pData + 1, pConstantData, ConstantCount * 16);
try
{
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETVERTEXSHADERCONST,
pData,
sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) + ConstantCount * 16,
!m_bEmulate && m_bDX8Dev && m_bTLHal);
}
catch(HRESULT hr)
{
delete[] pData;
throw hr;
}
delete[] pData;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::InsertPixelShaderConstant"
void CStateSets::InsertPixelShaderConstant(DWORD Register,
CONST VOID* pConstantData,
DWORD ConstantCount)
{
LPVOID pData = new BYTE[sizeof(D3DHAL_DP2SETPIXELSHADERCONST) + ConstantCount * 16];
if(pData == 0)
{
throw E_OUTOFMEMORY;
}
((LPD3DHAL_DP2SETPIXELSHADERCONST)pData)->dwRegister = Register;
((LPD3DHAL_DP2SETPIXELSHADERCONST)pData)->dwCount = ConstantCount;
memcpy((LPD3DHAL_DP2SETPIXELSHADERCONST)pData + 1, pConstantData, ConstantCount * 16);
try
{
m_pCurrentStateSet->InsertCommand(D3DDP2OP_SETPIXELSHADERCONST,
pData,
sizeof(D3DHAL_DP2SETPIXELSHADERCONST) + ConstantCount * 16,
!m_bEmulate && m_bDX8Dev);
}
catch(HRESULT hr)
{
delete[] pData;
throw hr;
}
delete[] pData;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSets::Execute"
void CStateSets::Execute(CD3DBase *pDevI, DWORD dwHandle)
{
#if DBG
if (dwHandle >= m_dwMaxSets)
{
D3D_ERR("Invalid state block handle");
throw D3DERR_INVALIDCALL;
}
#endif
CStateSet *pStateSet = &m_pStateSets[dwHandle];
#if DBG
if (!(pStateSet->m_dwStateSetFlags & __STATESET_INITIALIZED))
{
D3D_ERR("State block not initialized");
throw D3DERR_INVALIDCALL;
}
#endif
// Parse recorded data first
pStateSet->Execute(pDevI, TRUE);
// If the hardware buffer is not empty, we pass recorded data to it
if (pStateSet->m_dwDeviceHandle != __INVALIDHANDLE)
{
pStateSet->Execute(pDevI, FALSE);
if((pDevI->m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING) == 0 || (pStateSet->m_dwStateSetFlags & __STATESET_HASONLYVERTEXSTATE) == 0)
{
pDevI->m_pDDI->InsertStateSetOp(D3DHAL_STATESETEXECUTE, pStateSet->m_dwDeviceHandle, (D3DSTATEBLOCKTYPE)0);
}
else
{
pStateSet->m_dwStateSetFlags &= ~__STATESET_HASONLYVERTEXSTATE;
}
}
}
//=====================================================================
// CStateSet interface
//
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSet::Release"
HRESULT CStateSet::Release()
{
if (!(m_dwStateSetFlags & __STATESET_INITIALIZED))
return D3DERR_INVALIDCALL;
m_dwStateSetFlags &= ~__STATESET_INITIALIZED;
// Parse the FEOnly buffer and release all the VB/IB/Texture handles.
DWORD *p;
DWORD dwSize;
DWORD *pEnd;
p = (DWORD*)m_FEOnlyBuffer.m_pBuffer;
dwSize = m_FEOnlyBuffer.m_dwCurrentSize;
pEnd = (DWORD*)((BYTE*)p + dwSize);
while (p < pEnd)
{
LPD3DHAL_DP2COMMAND pCommand = (LPD3DHAL_DP2COMMAND)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
switch ((D3DHAL_DP2OPERATION)pCommand->bCommand)
{
case D3DDP2OP_RENDERSTATE:
p = (DWORD *)((D3DHAL_DP2RENDERSTATE *)p + pCommand->wStateCount);
break;
case D3DDP2OP_SETLIGHT:
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETLIGHT pData = (LPD3DHAL_DP2SETLIGHT)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETLIGHT));
switch (pData->dwDataType)
{
case D3DHAL_SETLIGHT_ENABLE:
case D3DHAL_SETLIGHT_DISABLE:
break;
case D3DHAL_SETLIGHT_DATA:
p = (DWORD *)((BYTE *)p + sizeof(D3DLIGHT8));
break;
}
}
break;
case D3DDP2OP_SETMATERIAL:
p = (DWORD *)((D3DHAL_DP2SETMATERIAL *)p + pCommand->wStateCount);
break;
case D3DDP2OP_SETTRANSFORM:
p = (DWORD *)((D3DHAL_DP2SETTRANSFORM *)p + pCommand->wStateCount);
break;
case D3DDP2OP_TEXTURESTAGESTATE:
p = (DWORD *)((D3DHAL_DP2TEXTURESTAGESTATE *)p +
pCommand->wStateCount);
break;
case D3DDP2OP_FRONTENDDATA:
{
CBaseTexture* pTexOld = NULL;
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FRONTENDDATA pData = (LPD3DHAL_DP2FRONTENDDATA)p;
pTexOld = CBaseTexture::SafeCast(pData->pTexture);
if( pTexOld )
pTexOld->DecrementUseCount();
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FRONTENDDATA));
}
break;
}
case D3DDP2OP_FESETVB:
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETVB pData = (LPD3DHAL_DP2FESETVB)p;
if( pData->pBuf )
pData->pBuf->DecrementUseCount();
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETVB));
}
break;
case D3DDP2OP_FESETIB:
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETIB pData = (LPD3DHAL_DP2FESETIB)p;
if( pData->pBuf )
pData->pBuf->DecrementUseCount();
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETIB));
}
break;
case D3DDP2OP_FESETPAL:
p = (DWORD *)((D3DHAL_DP2FESETPAL *)p + pCommand->wStateCount);
break;
case D3DDP2OP_VIEWPORTINFO:
// The next command has to be D3DDP2OP_ZRANGE
p = (DWORD *)((BYTE *)p +
( sizeof(D3DHAL_DP2VIEWPORTINFO) +
sizeof(D3DHAL_DP2COMMAND) +
sizeof(D3DHAL_DP2ZRANGE ) ) *
pCommand->wStateCount );
break;
case D3DDP2OP_SETCLIPPLANE:
p = (DWORD *)((D3DHAL_DP2SETCLIPPLANE *)p + pCommand->wStateCount);
break;
case D3DDP2OP_SETVERTEXSHADER:
p = (DWORD *)((D3DHAL_DP2VERTEXSHADER *)p + pCommand->wStateCount);
break;
case D3DDP2OP_SETPIXELSHADER:
p = (DWORD *)((D3DHAL_DP2PIXELSHADER *)p + pCommand->wStateCount);
break;
case D3DDP2OP_SETVERTEXSHADERCONST:
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETVERTEXSHADERCONST pData = (LPD3DHAL_DP2SETVERTEXSHADERCONST)p;
p = (DWORD*)((BYTE*)p +
sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) +
pData->dwCount * 16);
}
break;
case D3DDP2OP_SETPIXELSHADERCONST:
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETPIXELSHADERCONST pData = (LPD3DHAL_DP2SETPIXELSHADERCONST)p;
p = (DWORD*)((BYTE*)p +
sizeof(D3DHAL_DP2SETPIXELSHADERCONST) +
pData->dwCount * 16);
}
break;
#ifdef DBG
default:
DXGASSERT(FALSE);
#endif
}
}
m_FEOnlyBuffer.Reset();
m_DriverBuffer.Reset();
return D3D_OK;
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSet::InsertCommand"
void CStateSet::InsertCommand(D3DHAL_DP2OPERATION op, LPVOID pData,
DWORD dwDataSize,
BOOL bDriverCanHandle)
{
if (op == D3DDP2OP_TEXTURESTAGESTATE ||
(op == D3DDP2OP_RENDERSTATE &&
((LPD3DHAL_DP2RENDERSTATE)pData)->RenderState >= D3DRENDERSTATE_WRAP0 &&
((LPD3DHAL_DP2RENDERSTATE)pData)->RenderState <= D3DRENDERSTATE_WRAP7))
{
m_dwStateSetFlags |= __STATESET_NEEDCHECKREMAPPING;
}
if (bDriverCanHandle)
m_DriverBuffer.InsertCommand(op, pData, dwDataSize);
else
m_FEOnlyBuffer.InsertCommand(op, pData, dwDataSize);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSet::Execute"
void CStateSet::Execute(CD3DBase *pBaseDev, BOOL bFrontEndBuffer)
{
DWORD *p;
DWORD dwSize;
DWORD *pEnd;
// The device is not pure, so we can cast
DXGASSERT((pBaseDev->BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0);
CD3DHal *pDevI = static_cast<CD3DHal*>(pBaseDev);
D3DFE_PROCESSVERTICES* pv = pDevI->m_pv;
try
{
// Texture stages could be re-mapped during texture transform processing.
// Before we set new values we have to restore original ones
if (pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES &&
m_dwStateSetFlags & __STATESET_NEEDCHECKREMAPPING)
{
RestoreTextureStages(pDevI);
pDevI->ForceFVFRecompute();
}
if (bFrontEndBuffer)
{
p = (DWORD*)m_FEOnlyBuffer.m_pBuffer;
dwSize = m_FEOnlyBuffer.m_dwCurrentSize;
}
else
{
p = (DWORD*)m_DriverBuffer.m_pBuffer;
dwSize = m_DriverBuffer.m_dwCurrentSize;
pDevI->m_dwRuntimeFlags |= D3DRT_EXECUTESTATEMODE;
m_dwStateSetFlags |= __STATESET_HASONLYVERTEXSTATE;
}
pEnd = (DWORD*)((BYTE*)p + dwSize);
while (p < pEnd)
{
LPD3DHAL_DP2COMMAND pCommand = (LPD3DHAL_DP2COMMAND)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
switch ((D3DHAL_DP2OPERATION)pCommand->bCommand)
{
case D3DDP2OP_RENDERSTATE:
{
if(pDevI->m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE)
{
m_dwStateSetFlags &= ~__STATESET_HASONLYVERTEXSTATE;
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
D3DRENDERSTATETYPE dwState = (D3DRENDERSTATETYPE)*p++;
DWORD dwValue = *p++;
if ( (pDevI->rstates[dwState] != dwValue)
#if DBG
&& (dwState != D3DRS_DEBUGMONITORTOKEN) // don't filter these
#endif
)
{
if (!pDevI->rsVec.IsBitSet(dwState))
{ // Fast path. We do not need any processing done in UpdateInternalState other than updating rstates array
pDevI->rstates[dwState] = dwValue;
}
else
{
pDevI->UpdateInternalState(dwState, dwValue);
}
}
else
{
D3D_WARN(4,"Ignoring redundant SetRenderState %d", dwState);
}
}
}
else
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
D3DRENDERSTATETYPE dwState = (D3DRENDERSTATETYPE)*p++;
DWORD dwValue = *p++;
if ( (pDevI->rstates[dwState] != dwValue)
#if DBG
&& (dwState != D3DRS_DEBUGMONITORTOKEN) // don't filter these
#endif
)
{
if (!pDevI->rsVec.IsBitSet(dwState))
{ // Fast path. We do not need any processing done in UpdateInternalState other than updating rstates array
pDevI->rstates[dwState] = dwValue;
pDevI->m_pDDI->SetRenderState(dwState, dwValue);
}
else
{
pDevI->UpdateInternalState(dwState, dwValue);
// Vertex processing only render states will be passed to the
// driver when we switch to the hardware vertex processing mode
if ((!(pDevI->rsVertexProcessingOnly.IsBitSet(dwState) &&
pDevI->m_dwRuntimeFlags & D3DRT_RSSOFTWAREPROCESSING)))
{
if (pDevI->CanHandleRenderState(dwState))
{
pDevI->m_pDDI->SetRenderState(dwState, dwValue);
}
}
}
}
else
{
D3D_WARN(4,"Ignoring redundant SetRenderState %d", dwState);
}
}
}
break;
}
case D3DDP2OP_SETLIGHT:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETLIGHT pData = (LPD3DHAL_DP2SETLIGHT)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETLIGHT));
switch (pData->dwDataType)
{
case D3DHAL_SETLIGHT_ENABLE:
pDevI->LightEnableI( pData->dwIndex, TRUE );
break;
case D3DHAL_SETLIGHT_DISABLE:
pDevI->LightEnableI( pData->dwIndex, FALSE );
break;
case D3DHAL_SETLIGHT_DATA:
pDevI->SetLightI(pData->dwIndex, (D3DLIGHT8 *)p);
p = (LPDWORD)((LPBYTE)p + sizeof(D3DLIGHT8));
break;
}
}
break;
}
case D3DDP2OP_SETMATERIAL:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETMATERIAL pData = (LPD3DHAL_DP2SETMATERIAL)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETMATERIAL));
pDevI->SetMaterialFast((D3DMATERIAL8*)pData);
}
break;
}
case D3DDP2OP_SETTRANSFORM:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
D3DHAL_DP2SETTRANSFORM *pData = (D3DHAL_DP2SETTRANSFORM*)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETTRANSFORM));
pDevI->SetTransformI(pData->xfrmType, &pData->matrix);
}
break;
}
case D3DDP2OP_TEXTURESTAGESTATE:
{
if (pDevI->m_dwRuntimeFlags & D3DRT_EXECUTESTATEMODE)
{
m_dwStateSetFlags &= ~__STATESET_HASONLYVERTEXSTATE;
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2TEXTURESTAGESTATE pData = (LPD3DHAL_DP2TEXTURESTAGESTATE)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2TEXTURESTAGESTATE));
DWORD dwStage = pData->wStage;
DWORD dwState = pData->TSState;
DWORD dwValue = pData->dwValue;
if (pDevI->tsstates[dwStage][dwState] != dwValue)
{
// Fast path. We do not need any processing done in UpdateInternalTSS other than updating tsstates array
if (pDevI->NeedInternalTSSUpdate(dwState))
{
pDevI->UpdateInternalTextureStageState(dwStage, (D3DTEXTURESTAGESTATETYPE)dwState, &dwValue);
}
else
{
pDevI->tsstates[dwStage][dwState] = dwValue;
}
}
else
{
D3D_WARN(4,"Ignoring redundant SetTextureStageState Stage: %d, State: %d", dwStage, dwState);
}
}
}
else
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2TEXTURESTAGESTATE pData = (LPD3DHAL_DP2TEXTURESTAGESTATE)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2TEXTURESTAGESTATE));
DWORD dwStage = pData->wStage;
DWORD dwState = pData->TSState;
DWORD dwValue = pData->dwValue;
if (pDevI->tsstates[dwStage][dwState] != dwValue)
{
// Fast path. We do not need any processing done in UpdateInternalTSS other than updating tsstates array
if (pDevI->NeedInternalTSSUpdate(dwState))
{
if(pDevI->UpdateInternalTextureStageState(dwStage, (D3DTEXTURESTAGESTATETYPE)dwState, &dwValue))
continue;
}
else
{
pDevI->tsstates[dwStage][dwState] = dwValue;
}
if (dwStage >= pDevI->m_dwMaxTextureBlendStages)
continue;
pDevI->m_pDDI->SetTSS(dwStage, (D3DTEXTURESTAGESTATETYPE)dwState, dwValue);
}
else
{
D3D_WARN(4,"Ignoring redundant SetTextureStageState Stage: %d, State: %d", dwStage, dwState);
}
}
}
break;
}
case D3DDP2OP_FRONTENDDATA:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FRONTENDDATA pData = (LPD3DHAL_DP2FRONTENDDATA)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FRONTENDDATA));
HRESULT ret = pDevI->SetTexture(pData->wStage, pData->pTexture);
if (ret != D3D_OK)
throw ret;
}
break;
}
case D3DDP2OP_FESETVB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETVB pData = (LPD3DHAL_DP2FESETVB)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETVB));
HRESULT ret = pDevI->SetStreamSource(pData->wStream, pData->pBuf, pData->dwStride);
if (ret != D3D_OK)
throw ret;
}
break;
}
case D3DDP2OP_FESETIB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETIB pData = (LPD3DHAL_DP2FESETIB)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETIB));
HRESULT ret = pDevI->SetIndices(pData->pBuf, pData->dwBase);
if (ret != D3D_OK)
throw ret;
}
break;
}
case D3DDP2OP_FESETPAL:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETPAL pData = (LPD3DHAL_DP2FESETPAL)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETPAL));
if( pData->dwPaletteNumber != __INVALIDPALETTE )
{
HRESULT ret = pDevI->SetCurrentTexturePalette(pData->dwPaletteNumber);
if (ret != D3D_OK)
throw ret;
}
}
break;
}
case D3DDP2OP_VIEWPORTINFO:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
D3DVIEWPORT8 viewport;
LPD3DHAL_DP2VIEWPORTINFO lpVwpData = (LPD3DHAL_DP2VIEWPORTINFO)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2VIEWPORTINFO));
viewport.X = lpVwpData->dwX;
viewport.Y = lpVwpData->dwY;
viewport.Width = lpVwpData->dwWidth;
viewport.Height = lpVwpData->dwHeight;
// The next command has to be D3DDP2OP_ZRANGE
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
LPD3DHAL_DP2ZRANGE pData = (LPD3DHAL_DP2ZRANGE)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2ZRANGE));
viewport.MinZ = pData->dvMinZ;
viewport.MaxZ = pData->dvMaxZ;
pDevI->SetViewportI(&viewport);
}
break;
}
case D3DDP2OP_SETCLIPPLANE:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
D3DHAL_DP2SETCLIPPLANE *pData = (D3DHAL_DP2SETCLIPPLANE*)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETCLIPPLANE));
pDevI->SetClipPlaneI(pData->dwIndex, pData->plane);
}
break;
}
case D3DDP2OP_SETVERTEXSHADER:
{
// Optimization, dont loop, use the last one.
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2VERTEXSHADER pData = (LPD3DHAL_DP2VERTEXSHADER)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2VERTEXSHADER));
if( pData->dwHandle != 0 )
{
pDevI->SetVertexShader(pData->dwHandle);
}
else
{
pDevI->m_dwCurrentShaderHandle = 0;
}
}
pDevI->m_pDDI->ResetVertexShader();
break;
}
case D3DDP2OP_SETPIXELSHADER:
{
m_dwStateSetFlags &= ~__STATESET_HASONLYVERTEXSTATE;
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2PIXELSHADER pData = (LPD3DHAL_DP2PIXELSHADER)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2PIXELSHADER));
pDevI->SetPixelShaderFast(pData->dwHandle);
}
break;
}
case D3DDP2OP_SETVERTEXSHADERCONST:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETVERTEXSHADERCONST pData = (LPD3DHAL_DP2SETVERTEXSHADERCONST)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) + pData->dwCount * 16);
pDevI->SetVertexShaderConstantI(pData->dwRegister, pData + 1, pData->dwCount);
}
break;
}
case D3DDP2OP_SETPIXELSHADERCONST:
{
m_dwStateSetFlags &= ~__STATESET_HASONLYVERTEXSTATE;
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETPIXELSHADERCONST pData = (LPD3DHAL_DP2SETPIXELSHADERCONST)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETPIXELSHADERCONST) + pData->dwCount * 16);
pDevI->SetPixelShaderConstantFast(pData->dwRegister, pData + 1, pData->dwCount);
}
break;
}
#ifdef DBG
default:
DXGASSERT(FALSE);
#endif
}
}
pDevI->m_dwRuntimeFlags &= ~D3DRT_EXECUTESTATEMODE;
}
catch(HRESULT ret)
{
pDevI->m_dwRuntimeFlags &= ~D3DRT_EXECUTESTATEMODE;
m_dwStateSetFlags &= ~__STATESET_HASONLYVERTEXSTATE;
throw ret;
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSet::Capture"
void CStateSet::Capture(CD3DBase *pBaseDev, BOOL bFrontEndBuffer)
{
DWORD *p;
DWORD dwSize;
DWORD *pEnd;
// The device is not pure, so we can cast
DXGASSERT((pBaseDev->BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0);
CD3DHal *pDevI = static_cast<CD3DHal*>(pBaseDev);
D3DFE_PROCESSVERTICES* pv = pDevI->m_pv;
// Texture coordinate indices must be restored before capturing, because
// we do not call GetTextureStageState but access tsstates directly
if (pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
{
RestoreTextureStages(pDevI);
pDevI->ForceFVFRecompute();
}
if (bFrontEndBuffer)
{
p = (DWORD*)m_FEOnlyBuffer.m_pBuffer;
dwSize = m_FEOnlyBuffer.m_dwCurrentSize;
}
else
{
p = (DWORD*)m_DriverBuffer.m_pBuffer;
dwSize = m_DriverBuffer.m_dwCurrentSize;
}
pEnd = (DWORD*)((BYTE*)p + dwSize);
while (p < pEnd)
{
LPD3DHAL_DP2COMMAND pCommand = (LPD3DHAL_DP2COMMAND)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
switch ((D3DHAL_DP2OPERATION)pCommand->bCommand)
{
case D3DDP2OP_RENDERSTATE:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
const D3DRENDERSTATETYPE state = (D3DRENDERSTATETYPE)*p++;
*p++ = pDevI->rstates[state];
}
break;
}
case D3DDP2OP_SETLIGHT:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETLIGHT pData = (LPD3DHAL_DP2SETLIGHT)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETLIGHT));
LPDIRECT3DLIGHTI pLight =
static_cast<DIRECT3DLIGHTI *>
((*pDevI->m_pLightArray)[pData->dwIndex].m_pObj);
if(pData->dwIndex >= pDevI->m_pLightArray->GetSize())
{
D3D_ERR("Unable to capture light state (light not set?)");
throw D3DERR_INVALIDCALL;
}
switch (pData->dwDataType)
{
case D3DHAL_SETLIGHT_ENABLE:
if(!pLight->Enabled())
pData->dwDataType = D3DHAL_SETLIGHT_DISABLE;
break;
case D3DHAL_SETLIGHT_DISABLE:
if(pLight->Enabled())
pData->dwDataType = D3DHAL_SETLIGHT_ENABLE;
break;
case D3DHAL_SETLIGHT_DATA:
*((D3DLIGHT8*)p) = pLight->m_Light;
p = (LPDWORD)((LPBYTE)p + sizeof(D3DLIGHT8));
break;
}
}
break;
}
case D3DDP2OP_SETMATERIAL:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETMATERIAL pData = (LPD3DHAL_DP2SETMATERIAL)p;
*pData = *((LPD3DHAL_DP2SETMATERIAL)&pv->lighting.material);
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETMATERIAL));
}
break;
}
case D3DDP2OP_SETTRANSFORM:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETTRANSFORM pData = (LPD3DHAL_DP2SETTRANSFORM)p;
DWORD state = pData->xfrmType;
if ((DWORD)state >= __WORLDMATRIXBASE &&
(DWORD)state < __WORLDMATRIXBASE + __MAXWORLDMATRICES)
{
UINT index = (DWORD)state - __WORLDMATRIXBASE;
pData->matrix = *((LPD3DMATRIX)&pv->world[index]);
}
else
switch(pData->xfrmType)
{
case D3DTRANSFORMSTATE_VIEW:
pData->matrix = *((LPD3DMATRIX)&pv->view);
break;
case D3DTRANSFORMSTATE_PROJECTION:
pData->matrix = *((LPD3DMATRIX)&pDevI->transform.proj);
break;
case D3DTRANSFORMSTATE_TEXTURE0:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[0]);
break;
case D3DTRANSFORMSTATE_TEXTURE1:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[1]);
break;
case D3DTRANSFORMSTATE_TEXTURE2:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[2]);
break;
case D3DTRANSFORMSTATE_TEXTURE3:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[3]);
break;
case D3DTRANSFORMSTATE_TEXTURE4:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[4]);
break;
case D3DTRANSFORMSTATE_TEXTURE5:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[5]);
break;
case D3DTRANSFORMSTATE_TEXTURE6:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[6]);
break;
case D3DTRANSFORMSTATE_TEXTURE7:
pData->matrix = *((LPD3DMATRIX)&pv->mTexture[7]);
break;
}
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETTRANSFORM));
}
break;
}
case D3DDP2OP_TEXTURESTAGESTATE:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2TEXTURESTAGESTATE pData = (LPD3DHAL_DP2TEXTURESTAGESTATE)p;
pData->dwValue = pDevI->tsstates[pData->wStage][pData->TSState];
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2TEXTURESTAGESTATE));
}
break;
}
case D3DDP2OP_FRONTENDDATA:
{
CBaseTexture* pTexOld = NULL;
CBaseTexture* pTexNew = NULL;
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FRONTENDDATA pData = (LPD3DHAL_DP2FRONTENDDATA)p;
pTexOld = CBaseTexture::SafeCast(pData->pTexture);
if( pTexOld )
pTexOld->DecrementUseCount();
pTexNew = pDevI->m_lpD3DMappedTexI[pData->wStage];
if( pTexNew )
pTexNew->IncrementUseCount();
if (pDevI->m_lpD3DMappedTexI[pData->wStage] != 0)
{
switch(pDevI->m_lpD3DMappedTexI[pData->wStage]->GetBufferDesc()->Type)
{
case D3DRTYPE_TEXTURE:
pData->pTexture = static_cast<IDirect3DTexture8*>(static_cast<CMipMap*>(pTexNew));
break;
case D3DRTYPE_CUBETEXTURE:
pData->pTexture = static_cast<IDirect3DCubeTexture8*>(static_cast<CCubeMap*>(pTexNew));
break;
case D3DRTYPE_VOLUMETEXTURE:
pData->pTexture = static_cast<IDirect3DVolumeTexture8*>(static_cast<CMipVolume*>(pTexNew));
break;
}
}
else
{
pData->pTexture = 0;
}
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FRONTENDDATA));
}
break;
}
case D3DDP2OP_FESETVB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETVB pData = (LPD3DHAL_DP2FESETVB)p;
if( pData->pBuf )
pData->pBuf->DecrementUseCount();
pData->pBuf = pDevI->m_pStream[pData->wStream].m_pVB;
if( pData->pBuf )
pData->pBuf->IncrementUseCount();
pData->dwStride = pDevI->m_pStream[pData->wStream].m_dwStride;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETVB));
}
break;
}
case D3DDP2OP_FESETIB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETIB pData = (LPD3DHAL_DP2FESETIB)p;
if( pData->pBuf )
pData->pBuf->DecrementUseCount();
pData->pBuf = pDevI->m_pIndexStream->m_pVBI;
if( pData->pBuf )
pData->pBuf->IncrementUseCount();
pData->dwBase = pDevI->m_pIndexStream->m_dwBaseIndex;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETIB));
}
break;
}
case D3DDP2OP_FESETPAL:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETPAL pData = (LPD3DHAL_DP2FESETPAL)p;
pData->dwPaletteNumber = pDevI->m_dwPalette;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETPAL));
}
break;
}
case D3DDP2OP_VIEWPORTINFO:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
D3DVIEWPORT8 viewport;
LPD3DHAL_DP2VIEWPORTINFO lpVwpData = (LPD3DHAL_DP2VIEWPORTINFO)p;
lpVwpData->dwX = pDevI->m_Viewport.X;
lpVwpData->dwY = pDevI->m_Viewport.Y;
lpVwpData->dwWidth = pDevI->m_Viewport.Width;
lpVwpData->dwHeight = pDevI->m_Viewport.Height;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2VIEWPORTINFO));
// The next command has to be D3DDP2OP_ZRANGE
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
LPD3DHAL_DP2ZRANGE pData = (LPD3DHAL_DP2ZRANGE)p;
pData->dvMinZ = pDevI->m_Viewport.MinZ;
pData->dvMaxZ = pDevI->m_Viewport.MaxZ;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2ZRANGE));
}
break;
}
case D3DDP2OP_SETCLIPPLANE:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETCLIPPLANE pData = (LPD3DHAL_DP2SETCLIPPLANE)p;
*((LPD3DVECTORH)pData->plane) = pDevI->transform.userClipPlane[pData->dwIndex];
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETCLIPPLANE));
}
break;
}
case D3DDP2OP_SETVERTEXSHADER:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2VERTEXSHADER pData = (LPD3DHAL_DP2VERTEXSHADER)p;
pData->dwHandle = pDevI->m_dwCurrentShaderHandle;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2VERTEXSHADER));
}
break;
}
case D3DDP2OP_SETPIXELSHADER:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2PIXELSHADER pData = (LPD3DHAL_DP2PIXELSHADER)p;
pData->dwHandle = pDevI->m_dwCurrentPixelShaderHandle;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2PIXELSHADER));
}
break;
}
case D3DDP2OP_SETVERTEXSHADERCONST:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETVERTEXSHADERCONST pData = (LPD3DHAL_DP2SETVERTEXSHADERCONST)p;
pDevI->m_pv->pGeometryFuncs->GetShaderConstants(pData->dwRegister, pData->dwCount, pData + 1);
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETVERTEXSHADERCONST) + pData->dwCount * 16);
}
break;
}
case D3DDP2OP_SETPIXELSHADERCONST:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2SETPIXELSHADERCONST pData = (LPD3DHAL_DP2SETPIXELSHADERCONST)p;
pDevI->GetPixelShaderConstantI(pData->dwRegister,
pData->dwCount,
pData + 1);
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2SETPIXELSHADERCONST) + pData->dwCount * 16);
}
break;
}
#ifdef DBG
default:
DXGASSERT(FALSE);
#endif
}
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSet::CreatePredefined"
void CStateSet::CreatePredefined(CD3DBase *pBaseDev, D3DSTATEBLOCKTYPE sbt)
{
static D3DRENDERSTATETYPE ALLrstates[] =
{
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,
D3DRS_POSITIONORDER,
D3DRS_NORMALORDER,
};
static D3DTEXTURESTAGESTATETYPE ALLtsstates[] =
{
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,
};
static D3DRENDERSTATETYPE PIXELrstates[] =
{
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 PIXELtsstates[] =
{
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,
};
static D3DRENDERSTATETYPE VERTEXrstates[] =
{
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,
D3DRS_POSITIONORDER,
D3DRS_NORMALORDER,
};
static D3DTEXTURESTAGESTATETYPE VERTEXtsstates[] =
{
D3DTSS_TEXCOORDINDEX,
D3DTSS_TEXTURETRANSFORMFLAGS
};
DWORD i;
BOOL bCapturePixelShaderState = TRUE;
// The device is not pure, so we can cast
DXGASSERT((pBaseDev->BehaviorFlags() & D3DCREATE_PUREDEVICE) == 0);
CD3DHal *pDevI = static_cast<CD3DHal*>(pBaseDev);
D3DFE_PROCESSVERTICES* pv = pDevI->m_pv;
// Texture coordinate indices must be restored before capturing, because
// we do not call GetTextureStageState but access tsstates directly
if (pv->dwDeviceFlags & D3DDEV_REMAPTEXTUREINDICES)
{
RestoreTextureStages(pDevI);
pDevI->ForceFVFRecompute();
}
switch(sbt)
{
case (D3DSTATEBLOCKTYPE)0:
break;
case D3DSBT_ALL:
for(i = 0; i < sizeof(ALLrstates) / sizeof(D3DRENDERSTATETYPE); ++i)
pDevI->m_pStateSets->InsertRenderState(ALLrstates[i], pDevI->rstates[ALLrstates[i]], pDevI->CanHandleRenderState(ALLrstates[i]));
for (i = 0; i < pDevI->m_dwMaxTextureBlendStages; i++)
for(DWORD j = 0; j < sizeof(ALLtsstates) / sizeof(D3DTEXTURESTAGESTATETYPE); ++j)
pDevI->m_pStateSets->InsertTextureStageState(i, ALLtsstates[j], pDevI->tsstates[i][ALLtsstates[j]]);
// Capture textures
for (i = 0; i < pDevI->m_dwMaxTextureBlendStages; i++)
{
IDirect3DBaseTexture8 *pTex;
if (pDevI->m_lpD3DMappedTexI[i] != 0)
{
switch(pDevI->m_lpD3DMappedTexI[i]->GetBufferDesc()->Type)
{
case D3DRTYPE_TEXTURE:
pTex = static_cast<IDirect3DTexture8*>(static_cast<CMipMap*>(pDevI->m_lpD3DMappedTexI[i]));
break;
case D3DRTYPE_CUBETEXTURE:
pTex = static_cast<IDirect3DCubeTexture8*>(static_cast<CCubeMap*>(pDevI->m_lpD3DMappedTexI[i]));
break;
case D3DRTYPE_VOLUMETEXTURE:
pTex = static_cast<IDirect3DVolumeTexture8*>(static_cast<CMipVolume*>(pDevI->m_lpD3DMappedTexI[i]));
break;
}
}
else
{
pTex = 0;
}
pDevI->m_pStateSets->InsertTexture(i, pTex);
}
// Capture current palette
pDevI->m_pStateSets->InsertCurrentTexturePalette(pDevI->m_dwPalette);
// Capture streams
for (i = 0; i < pDevI->m_dwNumStreams; i++)
{
pDevI->m_pStateSets->InsertStreamSource(i, pDevI->m_pStream[i].m_pVB, pDevI->m_pStream[i].m_dwStride);
}
pDevI->m_pStateSets->InsertIndices(pDevI->m_pIndexStream->m_pVBI, pDevI->m_pIndexStream->m_dwBaseIndex);
// Capture current viewport
pDevI->m_pStateSets->InsertViewport(&pDevI->m_Viewport);
// Capture current transforms
for (i = 0; i < __MAXWORLDMATRICES; i++)
{
pDevI->m_pStateSets->InsertTransform(D3DTS_WORLDMATRIX(i), (LPD3DMATRIX)&pv->world[i]);
}
pDevI->m_pStateSets->InsertTransform(D3DTRANSFORMSTATE_VIEW, (LPD3DMATRIX)&pv->view);
pDevI->m_pStateSets->InsertTransform(D3DTRANSFORMSTATE_PROJECTION, (LPD3DMATRIX)&pDevI->transform.proj);
for (i = 0; i < pDevI->m_dwMaxTextureBlendStages; i++)
{
pDevI->m_pStateSets->InsertTransform((D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0 + i), (LPD3DMATRIX)&pv->mTexture[i]);
}
// Capture current clip-planes
for (i = 0; i < pDevI->m_dwMaxUserClipPlanes; i++)
{
pDevI->m_pStateSets->InsertClipPlane(i, (LPD3DVALUE)&pDevI->transform.userClipPlane[i]);
}
// Capture current material
pDevI->m_pStateSets->InsertMaterial(&pv->lighting.material);
// Capture current lights
for (i = 0; i < pDevI->m_pLightArray->GetSize(); i++)
{
LPDIRECT3DLIGHTI pLight =
static_cast<DIRECT3DLIGHTI *>((*pDevI->m_pLightArray)[i].m_pObj);
if( pLight)
{
pDevI->m_pStateSets->InsertLight(i, &pLight->m_Light);
if(pLight->Enabled())
{
pDevI->m_pStateSets->InsertLightEnable(i, TRUE);
}
else
{
pDevI->m_pStateSets->InsertLightEnable(i, FALSE);
}
}
}
// Capture current shaders
if (D3DVSD_ISLEGACY(pDevI->m_dwCurrentShaderHandle))
{
pDevI->m_pStateSets->InsertVertexShader(pDevI->m_dwCurrentShaderHandle, TRUE);
}
else
{
CVShader* pShader = (CVShader*)pDevI->m_pVShaderArray->GetObject(pDevI->m_dwCurrentShaderHandle);
if (pShader->m_dwFlags & CVShader::SOFTWARE)
{
pDevI->m_pStateSets->InsertVertexShader(pDevI->m_dwCurrentShaderHandle, FALSE);
}
else
{
pDevI->m_pStateSets->InsertVertexShader(pDevI->m_dwCurrentShaderHandle, TRUE);
}
}
if( bCapturePixelShaderState )
pDevI->m_pStateSets->InsertPixelShader(pDevI->m_dwCurrentPixelShaderHandle);
// Capture shader constants. Use Microsoft's constants as a temp buffer
{
const UINT count = pDevI->m_MaxVertexShaderConst;
pDevI->GetVertexShaderConstant(0, pDevI->GeometryFuncsGuaranteed->m_VertexVM.GetRegisters()->m_c, count);
pDevI->m_pStateSets->InsertVertexShaderConstant(0, pDevI->GeometryFuncsGuaranteed->m_VertexVM.GetRegisters()->m_c, count);
}
// Capture pixel shader constants
if( bCapturePixelShaderState )
{
// Note this is hardcoded to 8. ff.ff supports 16 but here we capture only 8.
pDevI->m_pStateSets->InsertPixelShaderConstant(0, pDevI->m_PShaderConstReg, 8 );
}
break;
case D3DSBT_PIXELSTATE:
for(i = 0; i < sizeof(PIXELrstates) / sizeof(D3DRENDERSTATETYPE); ++i)
pDevI->m_pStateSets->InsertRenderState(PIXELrstates[i], pDevI->rstates[PIXELrstates[i]], pDevI->CanHandleRenderState(PIXELrstates[i]));
for (i = 0; i < pDevI->m_dwMaxTextureBlendStages; i++)
for(DWORD j = 0; j < sizeof(PIXELtsstates) / sizeof(D3DTEXTURESTAGESTATETYPE); ++j)
pDevI->m_pStateSets->InsertTextureStageState(i, PIXELtsstates[j], pDevI->tsstates[i][PIXELtsstates[j]]);
// Capture pixel shader constants
if( bCapturePixelShaderState )
pDevI->m_pStateSets->InsertPixelShaderConstant(0, pDevI->m_PShaderConstReg,
D3DPS_CONSTREG_MAX_DX8);
// Capture current pixel shader
if( bCapturePixelShaderState )
pDevI->m_pStateSets->InsertPixelShader(pDevI->m_dwCurrentPixelShaderHandle);
break;
case D3DSBT_VERTEXSTATE:
for(i = 0; i < sizeof(VERTEXrstates) / sizeof(D3DRENDERSTATETYPE); ++i)
pDevI->m_pStateSets->InsertRenderState(VERTEXrstates[i], pDevI->rstates[VERTEXrstates[i]], pDevI->CanHandleRenderState(VERTEXrstates[i]));
for (i = 0; i < pDevI->m_dwMaxTextureBlendStages; i++)
for(DWORD j = 0; j < sizeof(VERTEXtsstates) / sizeof(D3DTEXTURESTAGESTATETYPE); ++j)
pDevI->m_pStateSets->InsertTextureStageState(i, VERTEXtsstates[j], pDevI->tsstates[i][VERTEXtsstates[j]]);
// Capture current light enables
for (i = 0; i < pDevI->m_pLightArray->GetSize(); i++)
{
LPDIRECT3DLIGHTI pLight =
static_cast<DIRECT3DLIGHTI *>((*pDevI->m_pLightArray)[i].m_pObj);
if( pLight)
{
pDevI->m_pStateSets->InsertLight(i, &pLight->m_Light);
if(pLight->Enabled())
{
pDevI->m_pStateSets->InsertLightEnable(i, TRUE);
}
else
{
pDevI->m_pStateSets->InsertLightEnable(i, FALSE);
}
}
}
// Capture shader constants. Use Microsoft's constants as a temp buffer
{
const UINT count = pDevI->m_MaxVertexShaderConst;
pDevI->GetVertexShaderConstant(0, pDevI->GeometryFuncsGuaranteed->m_VertexVM.GetRegisters()->m_c, count);
pDevI->m_pStateSets->InsertVertexShaderConstant(0, pDevI->GeometryFuncsGuaranteed->m_VertexVM.GetRegisters()->m_c, count);
}
// Capture current vertex shader
if (D3DVSD_ISLEGACY(pDevI->m_dwCurrentShaderHandle))
{
pDevI->m_pStateSets->InsertVertexShader(pDevI->m_dwCurrentShaderHandle, TRUE);
}
else
{
CVShader* pShader = (CVShader*)pDevI->m_pVShaderArray->GetObject(pDevI->m_dwCurrentShaderHandle);
if (pShader->m_dwFlags & CVShader::SOFTWARE)
{
pDevI->m_pStateSets->InsertVertexShader(pDevI->m_dwCurrentShaderHandle, FALSE);
}
else
{
pDevI->m_pStateSets->InsertVertexShader(pDevI->m_dwCurrentShaderHandle, TRUE);
}
}
break;
default:
throw D3DERR_INVALIDCALL;
}
pDevI->m_pStateSets->EndSet();
pDevI->m_pDDI->WriteStateSetToDevice(sbt);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CPureStateSet::InsertCommand"
void CPureStateSet::InsertCommand(D3DHAL_DP2OPERATION op, LPVOID pData,
DWORD dwDataSize,
BOOL bDriverCanHandle)
{
switch(op)
{
case D3DDP2OP_FRONTENDDATA:
case D3DDP2OP_FESETVB:
case D3DDP2OP_FESETIB:
m_FEOnlyBuffer.InsertCommand(op, pData, dwDataSize);
break;
default:
m_DriverBuffer.InsertCommand(op, pData, dwDataSize);
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CPureStateSet::Execute"
void CPureStateSet::Execute(CD3DBase *pDevI, BOOL bFrontEndBuffer)
{
DWORD *p;
DWORD dwSize;
DWORD *pEnd;
if (bFrontEndBuffer)
{
p = (DWORD*)m_FEOnlyBuffer.m_pBuffer;
dwSize = m_FEOnlyBuffer.m_dwCurrentSize;
}
else
{
return;
}
pEnd = (DWORD*)((BYTE*)p + dwSize);
while (p < pEnd)
{
LPD3DHAL_DP2COMMAND pCommand = (LPD3DHAL_DP2COMMAND)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
switch ((D3DHAL_DP2OPERATION)pCommand->bCommand)
{
case D3DDP2OP_FRONTENDDATA:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FRONTENDDATA pData = (LPD3DHAL_DP2FRONTENDDATA)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FRONTENDDATA));
HRESULT ret = pDevI->SetTexture(pData->wStage, pData->pTexture);
if (ret != D3D_OK)
throw ret;
}
break;
}
case D3DDP2OP_FESETVB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETVB pData = (LPD3DHAL_DP2FESETVB)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETVB));
HRESULT ret = pDevI->SetStreamSource(pData->wStream, pData->pBuf, pData->dwStride);
if (ret != D3D_OK)
throw ret;
}
break;
}
case D3DDP2OP_FESETIB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETIB pData = (LPD3DHAL_DP2FESETIB)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETIB));
HRESULT ret = pDevI->SetIndices(pData->pBuf, pData->dwBase);
if (ret != D3D_OK)
throw ret;
}
break;
}
case D3DDP2OP_FESETPAL:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETPAL pData = (LPD3DHAL_DP2FESETPAL)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETPAL));
if( pData->dwPaletteNumber != __INVALIDPALETTE )
{
HRESULT ret = pDevI->SetCurrentTexturePalette(pData->dwPaletteNumber);
if (ret != D3D_OK)
throw ret;
}
}
break;
}
#ifdef DBG
default:
DXGASSERT(FALSE);
#endif
}
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CPureStateSet::Capture"
void CPureStateSet::Capture(CD3DBase *pDevI, BOOL bFrontEndBuffer)
{
DWORD *p;
DWORD dwSize;
DWORD *pEnd;
if (bFrontEndBuffer)
{
p = (DWORD*)m_FEOnlyBuffer.m_pBuffer;
dwSize = m_FEOnlyBuffer.m_dwCurrentSize;
}
else
{
return;
}
pEnd = (DWORD*)((BYTE*)p + dwSize);
while (p < pEnd)
{
LPD3DHAL_DP2COMMAND pCommand = (LPD3DHAL_DP2COMMAND)p;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2COMMAND));
switch ((D3DHAL_DP2OPERATION)pCommand->bCommand)
{
case D3DDP2OP_FRONTENDDATA:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FRONTENDDATA pData = (LPD3DHAL_DP2FRONTENDDATA)p;
CBaseTexture* pTexOld = NULL;
CBaseTexture* pTexNew = NULL;
pTexOld = CBaseTexture::SafeCast(pData->pTexture);
if( pTexOld )
pTexOld->DecrementUseCount();
pTexNew = pDevI->m_lpD3DMappedTexI[pData->wStage];
if( pTexNew )
pTexNew->IncrementUseCount();
if (pDevI->m_lpD3DMappedTexI[pData->wStage] != 0)
{
switch(pDevI->m_lpD3DMappedTexI[pData->wStage]->GetBufferDesc()->Type)
{
case D3DRTYPE_TEXTURE:
pData->pTexture = static_cast<IDirect3DTexture8*>(static_cast<CMipMap*>(pTexNew));
break;
case D3DRTYPE_CUBETEXTURE:
pData->pTexture = static_cast<IDirect3DCubeTexture8*>(static_cast<CCubeMap*>(pTexNew));
break;
case D3DRTYPE_VOLUMETEXTURE:
pData->pTexture = static_cast<IDirect3DVolumeTexture8*>(static_cast<CMipVolume*>(pTexNew));
break;
}
}
else
{
pData->pTexture = 0;
}
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FRONTENDDATA));
}
break;
}
case D3DDP2OP_FESETVB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETVB pData = (LPD3DHAL_DP2FESETVB)p;
if( pData->pBuf )
{
pData->pBuf->DecrementUseCount();
}
pData->pBuf = pDevI->m_pStream[pData->wStream].m_pVB;
if( pData->pBuf )
{
pData->pBuf->IncrementUseCount();
}
pData->dwStride = pDevI->m_pStream[pData->wStream].m_dwStride;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETVB));
}
break;
}
case D3DDP2OP_FESETIB:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETIB pData = (LPD3DHAL_DP2FESETIB)p;
pData->pBuf = pDevI->m_pIndexStream->m_pVBI;
if( pData->pBuf )
{
pData->pBuf->DecrementUseCount();
}
pData->dwBase = pDevI->m_pIndexStream->m_dwBaseIndex;
if( pData->pBuf )
{
pData->pBuf->IncrementUseCount();
}
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETIB));
}
break;
}
case D3DDP2OP_FESETPAL:
{
for(DWORD i = 0; i < (DWORD)pCommand->wStateCount; ++i)
{
LPD3DHAL_DP2FESETPAL pData = (LPD3DHAL_DP2FESETPAL)p;
pData->dwPaletteNumber = pDevI->m_dwPalette;
p = (DWORD*)((BYTE*)p + sizeof(D3DHAL_DP2FESETPAL));
}
break;
}
#ifdef DBG
default:
DXGASSERT(FALSE);
#endif
}
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CPureStateSet::CreatePredefined"
void CPureStateSet::CreatePredefined(CD3DBase *pDevI, D3DSTATEBLOCKTYPE sbt)
{
DWORD i;
// The device is not pure, so we can cast
switch(sbt)
{
case (D3DSTATEBLOCKTYPE)0:
break;
case D3DSBT_ALL:
// Capture textures
for (i = 0; i < pDevI->m_dwMaxTextureBlendStages; i++)
{
IDirect3DBaseTexture8 *pTex;
if (pDevI->m_lpD3DMappedTexI[i] != 0)
{
switch(pDevI->m_lpD3DMappedTexI[i]->GetBufferDesc()->Type)
{
case D3DRTYPE_TEXTURE:
pTex = static_cast<IDirect3DTexture8*>(static_cast<CMipMap*>(pDevI->m_lpD3DMappedTexI[i]));
break;
case D3DRTYPE_CUBETEXTURE:
pTex = static_cast<IDirect3DCubeTexture8*>(static_cast<CCubeMap*>(pDevI->m_lpD3DMappedTexI[i]));
break;
case D3DRTYPE_VOLUMETEXTURE:
pTex = static_cast<IDirect3DVolumeTexture8*>(static_cast<CMipVolume*>(pDevI->m_lpD3DMappedTexI[i]));
break;
}
}
else
{
pTex = 0;
}
pDevI->m_pStateSets->InsertTexture(i, pTex);
}
// Capture streams
for (i = 0; i < pDevI->m_dwNumStreams; i++)
{
pDevI->m_pStateSets->InsertStreamSource(i, pDevI->m_pStream[i].m_pVB, pDevI->m_pStream[i].m_dwStride);
}
pDevI->m_pStateSets->InsertIndices(pDevI->m_pIndexStream->m_pVBI, pDevI->m_pIndexStream->m_dwBaseIndex);
break;
case D3DSBT_PIXELSTATE:
break;
case D3DSBT_VERTEXSTATE:
break;
default:
throw D3DERR_INVALIDCALL;
}
pDevI->m_pStateSets->EndSet();
DWORD DeviceHandle;
pDevI->m_pStateSets->CreateNewDeviceHandle(&DeviceHandle);
pDevI->m_pDDI->InsertStateSetOp(D3DHAL_STATESETCREATE, DeviceHandle, sbt);
}
//=====================================================================
// CStateSetBuffer interface
//
#undef DPF_MODNAME
#define DPF_MODNAME "CStateSetBuffer::InsertCommand"
void CStateSetBuffer::InsertCommand(D3DHAL_DP2OPERATION op, LPVOID pData, DWORD dwDataSize)
{
const DWORD GROWSIZE = 1024;
if (m_pDP2CurrCommand != 0 && m_pDP2CurrCommand->bCommand == op)
{
if (dwDataSize + m_dwCurrentSize <= m_dwBufferSize)
{
++m_pDP2CurrCommand->wStateCount;
memcpy(m_pBuffer + m_dwCurrentSize, pData, dwDataSize);
m_dwCurrentSize += dwDataSize;
return;
}
}
// Check for space
if (sizeof(D3DHAL_DP2COMMAND) + dwDataSize + m_dwCurrentSize > m_dwBufferSize)
{
// We need to grow the buffer
DWORD dwNewBufferSize = max(m_dwBufferSize + GROWSIZE, sizeof(D3DHAL_DP2COMMAND) + dwDataSize + m_dwCurrentSize);
BYTE *pTmp = new BYTE[dwNewBufferSize];
if (pTmp == NULL)
{
D3D_ERR("Not enough memory to create state block buffer");
throw E_OUTOFMEMORY;
}
if (m_pBuffer)
{
memcpy(pTmp, m_pBuffer, m_dwCurrentSize);
delete [] m_pBuffer;
}
m_pBuffer = pTmp;
m_dwBufferSize = dwNewBufferSize;
}
// Add new instruction
m_pDP2CurrCommand = (LPD3DHAL_DP2COMMAND)(m_pBuffer + m_dwCurrentSize);
m_pDP2CurrCommand->bCommand = op;
m_pDP2CurrCommand->bReserved = 0;
m_pDP2CurrCommand->wStateCount = 1;
m_dwCurrentSize += sizeof(D3DHAL_DP2COMMAND);
memcpy(m_pBuffer + m_dwCurrentSize, pData, dwDataSize);
m_dwCurrentSize += dwDataSize;
return;
}