Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1249 lines
44 KiB

/******************************Module*Header**********************************\
*
* *******************
* * D3D SAMPLE CODE *
* *******************
*
* Module Name: d3dsset.c
*
* Content: State set (block) management
*
* Copyright (c) 1999-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#include "glint.h"
//-----------------------------------------------------------------------------
// This module implements an emulation mechanism for handling state blocks
// (which are a required feature of the DX7 DDI) for hardware that doesn't
// offer any silicon support of the feature. It works simply by recording the
// render states and texture stage states set during state block recording
// and then "plays" them back when execution of the stage state is requested.
// Internal data structures are interchangeable between an uncompressed
// version (for recording speed) and a compressed format (for memory
// efficiency) since it is anticipated some apps may request thousands of
// state blocks.
//
// The following symbols have to be replaced according to your perticular
// driver implementation:
// - HEAP_ALLOC
// - HEAP_FREE
// - DISPDBG
// - _D3D_ST_ProcessOneRenderState
// - _D3D_TXT_ParseTextureStageStates
//-----------------------------------------------------------------------------
#if DX7_D3DSTATEBLOCKS
//-----------------------------------------------------------------------------
//
// P3StateSetRec *__SB_FindStateSet
//
// Find a state identified by dwHandle starting from pRootSS.
// If not found, returns NULL.
//
//-----------------------------------------------------------------------------
P3StateSetRec *__SB_FindStateSet(P3_D3DCONTEXT *pContext,
DWORD dwHandle)
{
if (dwHandle <= pContext->dwMaxSSIndex)
{
return pContext->pIndexTableSS[dwHandle - 1];
}
else
{
DISPDBG((DBGLVL,"State set %x not found (Max = %x)",
dwHandle, pContext->dwMaxSSIndex));
return NULL;
}
} // __SB_FindStateSet
//-----------------------------------------------------------------------------
//
// void __SB_DumpStateSet
//
// Dump info stored in a state set
//
//-----------------------------------------------------------------------------
#define ELEMS_IN_ARRAY(a) ((sizeof(a)/sizeof(a[0])))
void __SB_DumpStateSet(P3StateSetRec *pSSRec)
{
DWORD i,j;
DISPDBG((DBGLVL,"__SB_DumpStateSet %x, Id=%x dwSSFlags=%x",
pSSRec,pSSRec->dwHandle,pSSRec->dwSSFlags));
if (!(pSSRec->dwSSFlags & SB_COMPRESSED))
{
// uncompressed state set
// Dump render states values
for (i=0; i< MAX_STATE; i++)
{
DISPDBG((DBGLVL,"RS %x = %x",i, pSSRec->uc.RenderStates[i]));
}
// Dump TSS's values
for (j=0; j<= SB_MAX_STAGES; j++)
{
for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++)
{
DISPDBG((DBGLVL,"TSS [%x] %x = %x",
j, i, pSSRec->uc.TssStates[j][i]));
}
}
// Dump RS bit masks
for (i=0; i< ELEMS_IN_ARRAY(pSSRec->uc.bStoredRS); i++)
{
DISPDBG((DBGLVL,"bStoredRS[%x] = %x",
i, pSSRec->uc.bStoredRS[i]));
}
// Dump TSS bit masks
for (j=0; j<= SB_MAX_STAGES; j++)
{
for (i=0; i< ELEMS_IN_ARRAY(pSSRec->uc.bStoredTSS[j]); i++)
{
DISPDBG((DBGLVL,"bStoredTSS[%x][%x] = %x",
j, i, pSSRec->uc.bStoredTSS[j][i]));
}
}
}
else
{
// compressed state set
D3DHAL_DP2COMMAND *pDP2Cmd;
D3DHAL_DP2RENDERSTATE *pDP2RenderState;
D3DHAL_DP2TEXTURESTAGESTATE *pDP2TSState;
pDP2Cmd = pSSRec->cc.pDP2RenderState;
if (pDP2Cmd)
{
DISPDBG((DBGLVL,"dwNumRS =%x", pDP2Cmd->wStateCount));
pDP2RenderState = (D3DHAL_DP2RENDERSTATE *)(pDP2Cmd + 1);
for (i=0; i< pDP2Cmd->wStateCount; i++, pDP2RenderState++)
{
DISPDBG((DBGLVL,"RS %x = %x",
pDP2RenderState->RenderState,
pDP2RenderState->dwState));
}
}
pDP2Cmd = pSSRec->cc.pDP2TextureStageState;
if (pDP2Cmd)
{
DISPDBG((DBGLVL,"dwNumTSS=%x", pDP2Cmd->wStateCount));
pDP2TSState = (D3DHAL_DP2TEXTURESTAGESTATE *)(pDP2Cmd + 1);
for (i = 0; i < pDP2Cmd->wStateCount; i++, pDP2TSState++)
{
DISPDBG((DBGLVL,"TSS [%x] %x = %x",
pDP2TSState->wStage,
pDP2TSState->TSState,
pDP2TSState->dwValue));
}
}
}
} // __SB_DumpStateSet
//-----------------------------------------------------------------------------
//
// void __SB_AddStateSetIndexTableEntry
//
// Add an antry to the index table. If necessary, grow it.
//-----------------------------------------------------------------------------
void __SB_AddStateSetIndexTableEntry(P3_D3DCONTEXT* pContext,
DWORD dwNewHandle,
P3StateSetRec *pNewSSRec)
{
DWORD dwNewSize;
P3StateSetRec **pNewIndexTableSS;
// If the current list is not large enough, we'll have to grow a new one.
if (dwNewHandle > pContext->dwMaxSSIndex)
{
// New size of our index table
// (round up dwNewHandle in steps of SSPTRS_PERPAGE)
dwNewSize = ((dwNewHandle -1 + SSPTRS_PERPAGE) / SSPTRS_PERPAGE)
* SSPTRS_PERPAGE;
// we have to grow our list
pNewIndexTableSS = (P3StateSetRec **)
HEAP_ALLOC( FL_ZERO_MEMORY,
dwNewSize*sizeof(P3StateSetRec *),
ALLOC_TAG_DX(2));
if (!pNewIndexTableSS)
{
// we weren't able to grow the list so we will keep the old one
// and (sigh) forget about this state set since that is the
// safest thing to do. We will delete also the state set structure
// since no one will otherwise be able to find it later.
DISPDBG((ERRLVL,"Out of mem growing state set list,"
" droping current state set"));
HEAP_FREE(pNewSSRec);
return;
}
if (pContext->pIndexTableSS)
{
// if we already had a previous list, we must transfer its data
memcpy(pNewIndexTableSS,
pContext->pIndexTableSS,
pContext->dwMaxSSIndex*sizeof(P3StateSetRec *));
//and get rid of it
HEAP_FREE(pContext->pIndexTableSS);
}
// New index table data
pContext->pIndexTableSS = pNewIndexTableSS;
pContext->dwMaxSSIndex = dwNewSize;
}
// Store our state set pointer into our access list
pContext->pIndexTableSS[dwNewHandle - 1] = pNewSSRec;
} // __SB_AddStateSetIndexTableEntry
//-----------------------------------------------------------------------------
//
// int __SB_GetCompressedSize
//
// Calculate the size of the compressed state set
//
//-----------------------------------------------------------------------------
int __SB_GetCompressedSize(P3_D3DCONTEXT* pContext,
P3StateSetRec* pUncompressedSS,
OffsetsCompSS* offsetSS)
{
DWORD dwSize;
DWORD dwCount;
int i, j;
// Calculate the size of fixed part
dwSize = sizeof(CompressedStateSet) + 2*sizeof(DWORD);
// Calculate size of the render states
dwCount = 0;
for (i = 0; i < MAX_STATE; i++)
{
if (IS_FLAG_SET(pUncompressedSS->uc.bStoredRS , i))
{
dwCount++;
}
}
if (dwCount)
{
offsetSS->dwOffDP2RenderState = dwSize;
dwSize += (sizeof(D3DHAL_DP2COMMAND) + dwCount * sizeof(D3DHAL_DP2RENDERSTATE));
}
// Calculate size of the texture stage states
dwCount = 0;
for (j = 0; j <= SB_MAX_STAGES; j++)
{
for (i = 0; i <= D3DTSS_TEXTURETRANSFORMFLAGS; i++)
{
if (IS_FLAG_SET(pUncompressedSS->uc.bStoredTSS[j] , i))
{
dwCount++;
}
}
}
if (dwCount)
{
offsetSS->dwOffDP2TextureStageState = dwSize;
dwSize += (sizeof(D3DHAL_DP2COMMAND) + dwCount * sizeof(D3DHAL_DP2TEXTURESTAGESTATE));
}
// Calculate size of Viewport and ZRange
if (pUncompressedSS->uc.dwFlags & SB_VIEWPORT_CHANGED)
{
offsetSS->dwOffDP2Viewport = dwSize;
dwSize += (sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2VIEWPORTINFO));
}
if (pUncompressedSS->uc.dwFlags & SB_ZRANGE_CHANGED)
{
offsetSS->dwOffDP2ZRange = dwSize;
dwSize += (sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2ZRANGE));
}
#if DX8_DDI
if (pUncompressedSS->uc.dwFlags & SB_INDICES_CHANGED)
{
offsetSS->dwOffDP2SetIndices = dwSize;
dwSize += (sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2SETINDICES));
}
dwCount = 0;
for (i = 0; i < D3DVS_INPUTREG_MAX_V1_1; i++)
{
if (pUncompressedSS->uc.dwFlags & (SB_STREAMSRC_CHANGED << i))
{
dwCount++;
}
}
if (dwCount)
{
offsetSS->dwOffDP2SetStreamSources = dwSize;
dwSize += (sizeof(D3DHAL_DP2COMMAND) + dwCount * sizeof(D3DHAL_DP2SETSTREAMSOURCE));
}
#endif // DX8_DDI
#if DX7_SB_TNL
// TODO, Calculate size needed for lights, clip planes, material, transformation
#endif // DX7_SB_TNL
#if DX7_SB_TNL
// TODO, Calculate size needed for {V|P} shader constants
#endif // DX7_SB_TNL
#if DX8_DDI
if (pUncompressedSS->uc.dwFlags & SB_CUR_VS_CHANGED)
{
offsetSS->dwOffDP2SetVertexShader = dwSize;
dwSize += (sizeof(D3DHAL_DP2COMMAND) + sizeof(D3DHAL_DP2VERTEXSHADER));
}
#endif // DX8_DDI
return (dwSize);
} // __SB_GetCompressedSize
//-----------------------------------------------------------------------------
//
// void __SB_CompressStateSet
//
// Compress a state set so it uses the minimum necessary space. Since we expect
// some apps to make extensive use of state sets we want to keep things tidy.
// Returns address of new structure (ir old, if it wasn't compressed)
//
//-----------------------------------------------------------------------------
P3StateSetRec * __SB_CompressStateSet(P3_D3DCONTEXT* pContext,
P3StateSetRec *pUncompressedSS)
{
P3StateSetRec *pCompressedSS;
LPBYTE pTmp;
OffsetsCompSS offsetSS;
DWORD i, j, dwSize, dwCount;
D3DHAL_DP2COMMAND* pDP2Cmd;
// Initialize the offset structure
memset(&offsetSS, 0, sizeof(OffsetsCompSS));
// Create a new state set of just the right size we need
dwSize = __SB_GetCompressedSize(pContext, pUncompressedSS, &offsetSS);
if (dwSize >= pUncompressedSS->uc.dwSize)
{
// it is not efficient to compress, leave uncompressed !
pUncompressedSS->dwSSFlags &= (~SB_COMPRESSED);
return pUncompressedSS;
}
pTmp = HEAP_ALLOC(FL_ZERO_MEMORY, dwSize, ALLOC_TAG_DX(3));
if (! pTmp)
{
DISPDBG((ERRLVL,"Not enough memory left to compress D3D state set"));
pUncompressedSS->dwSSFlags &= (~SB_COMPRESSED);
return pUncompressedSS;
}
pCompressedSS = (P3StateSetRec *)pTmp;
// Adjust data in new compressed state set
pCompressedSS->dwSSFlags |= SB_COMPRESSED;
pCompressedSS->dwHandle = pUncompressedSS->dwHandle;
// Set up render state in the compressed state set
if (offsetSS.dwOffDP2RenderState)
{
D3DHAL_DP2RENDERSTATE* pDP2RS;
pDP2Cmd = (D3DHAL_DP2COMMAND *)(pTmp + offsetSS.dwOffDP2RenderState);
pCompressedSS->cc.pDP2RenderState = pDP2Cmd;
pDP2Cmd->bCommand = D3DDP2OP_RENDERSTATE;
pDP2RS = (D3DHAL_DP2RENDERSTATE *)(pDP2Cmd + 1);
for (i = 0; i < MAX_STATE; i++)
{
if (IS_FLAG_SET(pUncompressedSS->uc.bStoredRS , i))
{
pDP2RS->RenderState = i;
pDP2RS->dwState = pUncompressedSS->uc.RenderStates[i];
pDP2RS++;
}
}
pDP2Cmd->wStateCount = (WORD)(pDP2RS - ((D3DHAL_DP2RENDERSTATE *)(pDP2Cmd + 1)));
}
// Set up texture stage state in the compress state set
if (offsetSS.dwOffDP2TextureStageState)
{
D3DHAL_DP2TEXTURESTAGESTATE* pDP2TSS;
pDP2Cmd = (D3DHAL_DP2COMMAND *)(pTmp + offsetSS.dwOffDP2TextureStageState);
pCompressedSS->cc.pDP2TextureStageState = pDP2Cmd;
pDP2Cmd->bCommand = D3DDP2OP_TEXTURESTAGESTATE;
pDP2TSS = (D3DHAL_DP2TEXTURESTAGESTATE *)(pDP2Cmd + 1);
for (j = 0; j < SB_MAX_STAGES; j++)
{
for (i = 0; i <= D3DTSS_TEXTURETRANSFORMFLAGS; i++)
{
if (IS_FLAG_SET(pUncompressedSS->uc.bStoredTSS[j] , i))
{
pDP2TSS->wStage = (WORD)j;
pDP2TSS->TSState = (WORD)i;
pDP2TSS->dwValue = pUncompressedSS->uc.TssStates[j][i];
pDP2TSS++;
}
}
}
pDP2Cmd->wStateCount = (WORD)(pDP2TSS - ((D3DHAL_DP2TEXTURESTAGESTATE *)(pDP2Cmd + 1)));
}
// Set up the viewport and zrange in the compressed state set
if (offsetSS.dwOffDP2Viewport)
{
D3DHAL_DP2VIEWPORTINFO* pDP2ViewPort;
pDP2Cmd = (D3DHAL_DP2COMMAND *)(pTmp + offsetSS.dwOffDP2Viewport);
pCompressedSS->cc.pDP2Viewport = pDP2Cmd;
pDP2Cmd->bCommand = D3DDP2OP_VIEWPORTINFO;
pDP2ViewPort = (D3DHAL_DP2VIEWPORTINFO *)(pDP2Cmd + 1);
*pDP2ViewPort = pUncompressedSS->uc.viewport;
}
if (offsetSS.dwOffDP2ZRange)
{
D3DHAL_DP2ZRANGE* pDP2ZRange;
pDP2Cmd = (D3DHAL_DP2COMMAND *)(pTmp + offsetSS.dwOffDP2ZRange);
pCompressedSS->cc.pDP2ZRange = pDP2Cmd;
pDP2Cmd->bCommand = D3DDP2OP_ZRANGE;
pDP2ZRange = (D3DHAL_DP2ZRANGE *)(pDP2Cmd + 1);
*pDP2ZRange = pUncompressedSS->uc.zRange;
}
#if DX8_DDI
// Set up the vertex shader in the compressed state set
if (offsetSS.dwOffDP2SetIndices)
{
D3DHAL_DP2SETINDICES* pDP2SetIndices;
pDP2Cmd = (D3DHAL_DP2COMMAND *)(pTmp + offsetSS.dwOffDP2SetIndices);
pCompressedSS->cc.pDP2SetIndices = pDP2Cmd;
pDP2Cmd->bCommand = D3DDP2OP_SETINDICES;
pDP2SetIndices = (D3DHAL_DP2SETINDICES *)(pDP2Cmd + 1);
*pDP2SetIndices = pUncompressedSS->uc.vertexIndex;
pDP2Cmd->wStateCount = 1;
}
// Set up the vertex shader in the compressed state set
if (offsetSS.dwOffDP2SetStreamSources)
{
D3DHAL_DP2SETSTREAMSOURCE* pDP2SetStmSrc;
pDP2Cmd = (D3DHAL_DP2COMMAND *)(pTmp + offsetSS.dwOffDP2SetStreamSources);
pCompressedSS->cc.pDP2SetStreamSources = pDP2Cmd;
pDP2Cmd->bCommand = D3DDP2OP_SETSTREAMSOURCE;
pDP2SetStmSrc = (D3DHAL_DP2SETSTREAMSOURCE *)(pDP2Cmd + 1);
for (i = 0; i < D3DVS_INPUTREG_MAX_V1_1; i++)
{
if (pUncompressedSS->uc.dwFlags & (SB_STREAMSRC_CHANGED << i))
{
*pDP2SetStmSrc = pUncompressedSS->uc.streamSource[i];
pDP2SetStmSrc++;
}
}
pDP2Cmd->wPrimitiveCount = (WORD)(pDP2SetStmSrc - ((D3DHAL_DP2SETSTREAMSOURCE *)(pDP2Cmd + 1)) );
}
#endif // DX8_DDI
#if DX7_SB_TNL
// TODO, set up light, material, transform, clip plane
#endif // DX7_SB_TNL
#if DX8_SB_SHADERS
// TODO, set up shader constants
#endif // DX8_SB_SHADERS
#if DX8_DDI
// Set up the vertex shader in the compressed state set
if (offsetSS.dwOffDP2SetVertexShader)
{
D3DHAL_DP2VERTEXSHADER* pDP2SetVtxShader;
pDP2Cmd = (D3DHAL_DP2COMMAND *)(pTmp + offsetSS.dwOffDP2SetVertexShader);
pCompressedSS->cc.pDP2SetVertexShader = pDP2Cmd;
pDP2Cmd->bCommand = D3DDP2OP_SETVERTEXSHADER;
pDP2SetVtxShader = (D3DHAL_DP2VERTEXSHADER *)(pDP2Cmd + 1);
pDP2SetVtxShader->dwHandle = pUncompressedSS->uc.dwCurVertexShader;
}
#endif // DX8_DDI
// Get rid of the old(uncompressed) one
HEAP_FREE(pUncompressedSS);
return pCompressedSS;
} // __SB_CompressStateSet
//-----------------------------------------------------------------------------
//
// void _D3D_SB_DeleteAllStateSets
//
// Delete any remaining state sets for cleanup purpouses
//
//-----------------------------------------------------------------------------
void _D3D_SB_DeleteAllStateSets(P3_D3DCONTEXT* pContext)
{
P3StateSetRec *pSSRec;
DWORD dwSSIndex;
DISPDBG((DBGLVL,"_D3D_SB_DeleteAllStateSets"));
if (pContext->pIndexTableSS)
{
for(dwSSIndex = 0; dwSSIndex < pContext->dwMaxSSIndex; dwSSIndex++)
{
if (pSSRec = pContext->pIndexTableSS[dwSSIndex])
{
HEAP_FREE(pSSRec);
}
}
// free fast index table
HEAP_FREE(pContext->pIndexTableSS);
}
} // _D3D_SB_DeleteAllStateSets
//-----------------------------------------------------------------------------
//
// void _D3D_SB_BeginStateSet
//
// Create a new state set identified by dwParam and start recording states
//
//-----------------------------------------------------------------------------
void _D3D_SB_BeginStateSet(P3_D3DCONTEXT* pContext, DWORD dwParam)
{
DWORD dwSSSize;
P3StateSetRec *pSSRec;
DISPDBG((DBGLVL,"_D3D_SB_BeginStateSet dwParam=%08lx",dwParam));
// Calculate the maximum size of the state set
dwSSSize = sizeof(P3StateSetRec);
#if DX7_SB_TNL
// TODO, Size depends on number of lights, clip planes
#endif // DX7_SB_TNL
#if DX8_SB_SHADERS
// TODO, size depends on number of vertext/pixel shaders
#endif // DX8_SB_SHADERS
// Create a new state set
pSSRec = (P3StateSetRec *)HEAP_ALLOC(FL_ZERO_MEMORY,
dwSSSize,
ALLOC_TAG_DX(4));
if (!pSSRec)
{
DISPDBG((ERRLVL,"Run out of memory for additional state sets"));
return;
}
// Remember handle to current state set
pSSRec->dwHandle = dwParam;
pSSRec->dwSSFlags &= (~SB_COMPRESSED);
// Remember the size of the uncompressed state set
pSSRec->uc.dwSize = dwSSSize;
#if DX7_SB_TNL
// TODO, Set up pointers for data used for lights, clip planes
#endif // DX7_SB_TNL
#if DX8_SB_SHADERS
// TODO, Set up pointers for data used for {V|P} shader constants
#endif // DX8_SB_SHADERS
// Get pointer to current recording state set
pContext->pCurrSS = pSSRec;
// Start recording mode
pContext->bStateRecMode = TRUE;
} // _D3D_SB_BeginStateSet
//-----------------------------------------------------------------------------
//
// void _D3D_SB_EndStateSet
//
// stop recording states - revert to executing them.
//
//-----------------------------------------------------------------------------
void _D3D_SB_EndStateSet(P3_D3DCONTEXT* pContext)
{
DWORD dwHandle;
P3StateSetRec *pNewSSRec;
DISPDBG((DBGLVL,"_D3D_SB_EndStateSet"));
if (pContext->pCurrSS)
{
dwHandle = pContext->pCurrSS->dwHandle;
// compress the current state set
// Note: after being compressed the uncompressed version is free'd.
pNewSSRec = __SB_CompressStateSet(pContext, pContext->pCurrSS);
__SB_AddStateSetIndexTableEntry(pContext, dwHandle, pNewSSRec);
}
// No state set being currently recorded
pContext->pCurrSS = NULL;
// End recording mode
pContext->bStateRecMode = FALSE;
} // _D3D_SB_EndStateSet
//-----------------------------------------------------------------------------
//
// void _D3D_SB_DeleteStateSet
//
// Delete the recorder state ste identified by dwParam
//
//-----------------------------------------------------------------------------
void _D3D_SB_DeleteStateSet(P3_D3DCONTEXT* pContext, DWORD dwParam)
{
P3StateSetRec *pSSRec;
DWORD i;
DISPDBG((DBGLVL,"_D3D_SB_DeleteStateSet dwParam=%08lx",dwParam));
if (pSSRec = __SB_FindStateSet(pContext, dwParam))
{
// Clear index table entry
pContext->pIndexTableSS[dwParam - 1] = NULL;
// Now delete the actual state set structure
HEAP_FREE(pSSRec);
}
} // _D3D_SB_DeleteStateSet
//-----------------------------------------------------------------------------
//
// void _D3D_SB_ExecuteStateSet
//
// Execute the render states and texture stage states of which a given
// state set is comprised. Distinguish between the compressed and
// uncomressed representations of records.
//
//-----------------------------------------------------------------------------
void _D3D_SB_ExecuteStateSet(P3_D3DCONTEXT* pContext, DWORD dwParam)
{
P3StateSetRec *pSSRec;
DWORD i,j;
DISPDBG((DBGLVL,"_D3D_SB_ExecuteStateSet dwParam=%08lx",dwParam));
if (pSSRec = __SB_FindStateSet(pContext, dwParam))
{
if (!(pSSRec->dwSSFlags & SB_COMPRESSED))
{
// uncompressed state set
// Execute any necessary render states
for (i=0; i< MAX_STATE; i++)
{
if (IS_FLAG_SET(pSSRec->uc.bStoredRS , i))
{
DWORD dwRSType, dwRSVal;
dwRSType = i;
dwRSVal = pSSRec->uc.RenderStates[dwRSType];
// Store the state in the context
pContext->RenderStates[dwRSType] = dwRSVal;
DISPDBG((DBGLVL,"_D3D_SB_ExecuteStateSet RS %x = %x",
dwRSType, dwRSVal));
// Process it
_D3D_ST_ProcessOneRenderState(pContext, dwRSType, dwRSVal);
}
}
// Execute any necessary TSS's
for (j=0; j<SB_MAX_STAGES; j++)
{
for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++)
{
if (IS_FLAG_SET(pSSRec->uc.bStoredTSS[j] , i))
{
D3DHAL_DP2TEXTURESTAGESTATE dp2TSS;
dp2TSS.TSState = (WORD)i;
dp2TSS.wStage = (WORD)j;
dp2TSS.dwValue = pSSRec->uc.TssStates[j][i];
DISPDBG((DBGLVL,
"_D3D_SB_ExecuteStateSet TSS %x [%x] = %x",
dp2TSS.TSState,
dp2TSS.wStage,
dp2TSS.dwValue));
// If a state set is changed by _D3D_SB_CaptureStateSet(),
// then texture filter values in it are DX6 semantic, otherwise
// it is DX8
if (pSSRec->dwSSFlags & SB_VAL_CAPTURED)
{
_D3D_TXT_ParseTextureStageStates(pContext,
&dp2TSS,
1,
FALSE); //It is already DX6
}
else
{
_D3D_TXT_ParseTextureStageStates(pContext,
&dp2TSS,
1,
TRUE);
}
}
}
}
// Excute viewport info, z range
if (pSSRec->uc.dwFlags & SB_VIEWPORT_CHANGED)
{
_D3D_OP_Viewport(pContext, &pSSRec->uc.viewport);
}
if (pSSRec->uc.dwFlags & SB_ZRANGE_CHANGED)
{
_D3D_OP_ZRange(pContext, &pSSRec->uc.zRange);
}
#if DX8_DDI
// Excute vertex indices and stream sources
if (pSSRec->uc.dwFlags & SB_INDICES_CHANGED)
{
_D3D_OP_MStream_SetIndices(pContext,
pSSRec->uc.vertexIndex.dwVBHandle,
pSSRec->uc.vertexIndex.dwStride);
}
for (i = 0; i < D3DVS_INPUTREG_MAX_V1_1; i++)
{
if (pSSRec->uc.dwFlags & (SB_STREAMSRC_CHANGED << i))
{
_D3D_OP_MStream_SetSrc(pContext,
pSSRec->uc.streamSource[i].dwStream,
pSSRec->uc.streamSource[i].dwVBHandle,
pSSRec->uc.streamSource[i].dwStride);
}
}
#endif // DX8_DDI
#if DX7_SB_TNL
// TODO, Execute any necessary state for lights, materials,
// transforms, clip planes
#endif // DX7_SB_TNL
#if DX8_SB_SHADERS
// TODO, Execute any necessary set current shader and set shader
// constants pairs
#endif // DX8_SB_SHADERS
#if DX8_DDI
// Note : This should be done after setting shader constants, since
// current shader may have to be set before changing constants
if (pSSRec->uc.dwFlags & SB_CUR_VS_CHANGED)
{
_D3D_OP_VertexShader_Set(pContext,
pSSRec->uc.dwCurVertexShader);
}
#endif // DX8_DDI
}
else
{
// compressed state set
// Execute any necessary RS's
if (pSSRec->cc.pDP2RenderState)
{
DISPDBG((DBGLVL, "_D3D_SB_ExecuteStateSet RenderState"));
_D3D_ST_ProcessRenderStates(pContext,
pSSRec->cc.pDP2RenderState->wStateCount,
(LPD3DSTATE)(pSSRec->cc.pDP2RenderState + 1),
FALSE);
}
// Execute any necessary TSS's
if (pSSRec->cc.pDP2TextureStageState)
{
DISPDBG((DBGLVL,"_D3D_SB_ExecuteStateSet TSS"));
// If a state set is changed by _D3D_SB_CaptureStateSet(),
// then texture filter values in it are DX6 semantic, otherwise
// it is DX8
if (pSSRec->dwSSFlags & SB_VAL_CAPTURED)
{
_D3D_TXT_ParseTextureStageStates(pContext,
(D3DHAL_DP2TEXTURESTAGESTATE *)(pSSRec->cc.pDP2TextureStageState + 1),
pSSRec->cc.pDP2TextureStageState->wStateCount,
FALSE); // It is already DX6
}
else
{
_D3D_TXT_ParseTextureStageStates(pContext,
(D3DHAL_DP2TEXTURESTAGESTATE *)(pSSRec->cc.pDP2TextureStageState + 1),
pSSRec->cc.pDP2TextureStageState->wStateCount,
TRUE);
}
}
// execute viewport info, z range
if (pSSRec->cc.pDP2Viewport)
{
_D3D_OP_Viewport(pContext,
((D3DHAL_DP2VIEWPORTINFO *)(pSSRec->cc.pDP2Viewport + 1))
);
}
if (pSSRec->cc.pDP2ZRange)
{
_D3D_OP_ZRange(pContext,
((D3DHAL_DP2ZRANGE *)(pSSRec->cc.pDP2ZRange + 1))
);
}
#if DX8_DDI
// Execute vertex index, stream, shader
if (pSSRec->cc.pDP2SetIndices)
{
D3DHAL_DP2SETINDICES* pDP2SetIndices;
pDP2SetIndices = (D3DHAL_DP2SETINDICES *)(pSSRec->cc.pDP2SetIndices + 1);
_D3D_OP_MStream_SetIndices(pContext,
pDP2SetIndices->dwVBHandle,
pDP2SetIndices->dwStride);
}
if (pSSRec->cc.pDP2SetStreamSources)
{
D3DHAL_DP2SETSTREAMSOURCE *pDP2SetStmSrc;
DISPDBG((DBGLVL,"More than 1 stream (%d)",
pSSRec->cc.pDP2SetStreamSources->wStateCount));
pDP2SetStmSrc = (D3DHAL_DP2SETSTREAMSOURCE *)(pSSRec->cc.pDP2SetStreamSources + 1);
ASSERTDD(pDP2SetStmSrc->dwStream == 0, "Wrong vertex stream");
for (i = 0; i < pSSRec->cc.pDP2SetStreamSources->wStateCount; i++, pDP2SetStmSrc++)
{
_D3D_OP_MStream_SetSrc(pContext,
pDP2SetStmSrc->dwStream,
pDP2SetStmSrc->dwVBHandle,
pDP2SetStmSrc->dwStride);
}
}
#endif // DX8_DDI
#if DX7_SB_TNL
// TODO, Execute any necessary state for lights, materials,
// transforms, clip planes
#endif // DX7_SB_TNL
#if DX8_SB_SHADERS
// TODO, Execute any necessary state for setting {V|P} shader constants
#endif // DX8_SB_SHADERS
#if DX8_DDI
// Execute current pixel shader (legacy FVF code)
if (pSSRec->cc.pDP2SetVertexShader)
{
_D3D_OP_VertexShader_Set(pContext,
((D3DHAL_DP2VERTEXSHADER *)(pSSRec->cc.pDP2SetVertexShader + 1))->dwHandle);
}
#endif // DX8_DDI
}
}
} // _D3D_SB_ExecuteStateSet
//-----------------------------------------------------------------------------
//
// void _D3D_SB_CaptureStateSet
//
// Capture the render states and texture stage states of which a given
// state set is comprised. Distinguish between the compressed and
// uncomressed representations of records. This functionality allows the
// app to have a push/pop state feature.
//
//-----------------------------------------------------------------------------
void _D3D_SB_CaptureStateSet(P3_D3DCONTEXT* pContext, DWORD dwParam)
{
P3StateSetRec *pSSRec;
DWORD i, j;
DISPDBG((DBGLVL,"_D3D_SB_CaptureStateSet dwParam=%08lx",dwParam));
if (pSSRec = __SB_FindStateSet(pContext, dwParam))
{
// Mark it as having DX6 texture filter values instead of DX8,
// so that _D3D_SB_ExecuteStateSet() uses the FALSE for the
// bTranslateDX8FilterValueToDX6 of _D3D_TXT_ParseTextureStageStates()
pSSRec->dwSSFlags |= SB_VAL_CAPTURED;
// Actually capture the values
if (!(pSSRec->dwSSFlags & SB_COMPRESSED))
{
// uncompressed state set
// Capture any necessary render states
for (i=0; i< MAX_STATE; i++)
if (IS_FLAG_SET(pSSRec->uc.bStoredRS , i))
{
pSSRec->uc.RenderStates[i] = pContext->RenderStates[i];
}
// Capture any necessary TSS's
for (j=0; j<SB_MAX_STAGES; j++)
{
for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++)
{
if (IS_FLAG_SET(pSSRec->uc.bStoredTSS[j] , i))
{
pSSRec->uc.TssStates[j][i] =
pContext->TextureStageState[j].m_dwVal[i];
}
}
}
// Capture viewport info, z range
if (pSSRec->uc.dwFlags & SB_VIEWPORT_CHANGED)
{
pSSRec->uc.viewport = pContext->ViewportInfo;
}
if (pSSRec->uc.dwFlags & SB_ZRANGE_CHANGED)
{
pSSRec->uc.zRange = pContext->ZRange;
}
#if DX8_DDI
// Capture vertex indices and stream sources
if (pSSRec->uc.dwFlags & SB_INDICES_CHANGED)
{
pSSRec->uc.vertexIndex.dwVBHandle = pContext->dwIndexHandle;
pSSRec->uc.vertexIndex.dwStride = pContext->dwIndicesStride;
}
// Note : P3 supports only one stream
for (i = 0; i < D3DVS_INPUTREG_MAX_V1_1; i++)
{
ASSERTDD(i == 0, "Wrong vertex stream");
if (pSSRec->uc.dwFlags & (SB_STREAMSRC_CHANGED << i))
{
pSSRec->uc.streamSource[i].dwStream = 0;
pSSRec->uc.streamSource[i].dwVBHandle = pContext->dwVBHandle;
pSSRec->uc.streamSource[i].dwStride = pContext->dwVerticesStride;
}
}
#endif // DX8_DDI
#if DX7_SB_TNL
// TODO, Capture any necessary state for lights, materials,
// transforms, clip planes
#endif // DX7_SB_TNL
#if DX8_SB_SHADERS
// TODO, Capture any necessary state for {V|P} shader constants
#endif // DX8_SB_SHADERS
#if DX8_DDI
// Capture the current vertex shader
if (pSSRec->uc.dwFlags & SB_CUR_VS_CHANGED)
{
pSSRec->uc.dwCurVertexShader = pContext->dwVertexType;
}
#endif // DX8_DDI
}
else
{
// compressed state set
// Capture any necessary render states
if (pSSRec->cc.pDP2RenderState)
{
D3DHAL_DP2RENDERSTATE* pDP2RS;
pDP2RS = (D3DHAL_DP2RENDERSTATE *)(pSSRec->cc.pDP2RenderState + 1);
for (i = 0; i < pSSRec->cc.pDP2RenderState->wStateCount; i++, pDP2RS++)
{
pDP2RS->dwState = pContext->RenderStates[pDP2RS->RenderState];
}
}
// Capture any necessary TSS's
if (pSSRec->cc.pDP2TextureStageState)
{
D3DHAL_DP2TEXTURESTAGESTATE* pDP2TSS;
pDP2TSS = (D3DHAL_DP2TEXTURESTAGESTATE *)(pSSRec->cc.pDP2TextureStageState + 1);
for (i = 0; i < pSSRec->cc.pDP2TextureStageState->wStateCount; i++, pDP2TSS++)
{
pDP2TSS->dwValue = pContext->TextureStageState[pDP2TSS->wStage].m_dwVal[pDP2TSS->TSState];
}
}
// Capture viewport info, z range
if (pSSRec->cc.pDP2Viewport)
{
*((D3DHAL_DP2VIEWPORTINFO *)(pSSRec->cc.pDP2Viewport + 1)) = pContext->ViewportInfo;
}
if (pSSRec->cc.pDP2ZRange)
{
*((D3DHAL_DP2ZRANGE *)(pSSRec->cc.pDP2ZRange + 1)) = pContext->ZRange;
}
#if DX8_DDI
// Capture vertex index, stream, shader
if (pSSRec->cc.pDP2SetIndices)
{
D3DHAL_DP2SETINDICES* pDP2SetIndices;
pDP2SetIndices = (D3DHAL_DP2SETINDICES *)(pSSRec->cc.pDP2SetIndices + 1);
pDP2SetIndices->dwVBHandle = pContext->dwIndexHandle;
pDP2SetIndices->dwStride = pContext->dwIndicesStride; // 2 | 4
}
if (pSSRec->cc.pDP2SetStreamSources)
{
D3DHAL_DP2SETSTREAMSOURCE* pDP2SetStmSrc;
pDP2SetStmSrc = (D3DHAL_DP2SETSTREAMSOURCE *)(pSSRec->cc.pDP2SetStreamSources + 1);
pDP2SetStmSrc->dwStream = 0; // Only stream for permedia 3
pDP2SetStmSrc->dwVBHandle = pContext->dwVBHandle;
pDP2SetStmSrc->dwStride = pContext->dwVerticesStride;
}
#endif // DX8_DDI
#if DX7_SB_TNL
// TODO, Capture any necessary state for lights, materials,
// transforms, clip planes
#endif // DX7_SB_TNL
#if DX8_SB_SHADERS
// TODO, Capture any necessary state for {V|P} shader constants
#endif // DX8_SB_SHADERS
#if DX8_DDI
// Capture current vertex shader
if (pSSRec->cc.pDP2SetVertexShader)
{
D3DHAL_DP2VERTEXSHADER* pSetVtxShader;
pSetVtxShader = (D3DHAL_DP2VERTEXSHADER *)(pSSRec->cc.pDP2SetVertexShader + 1);
pSetVtxShader->dwHandle = pContext->dwVertexType;
}
#endif // DX8_DDI
}
}
} // _D3D_SB_CaptureStateSet
//-----------------------------------------------------------------------------
// Recording happens between BeginStateSet and EndStateSet calls so we
// never need to deal with recording into a compressed state set (since
// compression happens in EndStateSet)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// void _D3D_SB_RecordStateSetRS
//
// Record this render state into the current state set being recorded
//
//-----------------------------------------------------------------------------
void _D3D_SB_RecordStateSetRS(P3_D3DCONTEXT* pContext,
DWORD dwRSType,
DWORD dwRSVal)
{
if (pContext->pCurrSS != NULL)
{
DISPDBG((DBGLVL,"Recording SB # %x : RS %x = %x",
pContext->pCurrSS->dwHandle,dwRSType,dwRSVal));
// Recording the state in an uncompressed stateblock
pContext->pCurrSS->uc.RenderStates[dwRSType] = dwRSVal;
FLAG_SET(pContext->pCurrSS->uc.bStoredRS, dwRSType);
}
} // _D3D_SB_RecordStateSetRS
//-----------------------------------------------------------------------------
//
// void _D3D_SB_RecordStateSetTSS
//
// Record this texture stage state into the current state set being recorded
//
//-----------------------------------------------------------------------------
void _D3D_SB_RecordStateSetTSS(P3_D3DCONTEXT* pContext,
DWORD dwTSStage,
DWORD dwTSState,
DWORD dwTSVal)
{
if (pContext->pCurrSS != NULL)
{
DISPDBG((DBGLVL,"Recording SB # %x : TSS %x [%x] = %x",
pContext->pCurrSS->dwHandle,dwTSState, dwTSStage, dwTSVal));
// Recording the state in an uncompressed stateblock
pContext->pCurrSS->uc.TssStates[dwTSStage][dwTSState] = dwTSVal;
FLAG_SET(pContext->pCurrSS->uc.bStoredTSS[dwTSStage], dwTSState);
}
} // _D3D_SB_RecordStateSetTSS
#if DX8_MULTSTREAMS
//-----------------------------------------------------------------------------
//
// void _D3D_SB_Record_VertexShader_Set
//
// Record this vertex shader set code into the current state set being recorded
//
//-----------------------------------------------------------------------------
void _D3D_SB_Record_VertexShader_Set(P3_D3DCONTEXT* pContext,
DWORD dwVtxShaderHandle)
{
if (pContext->pCurrSS != NULL)
{
ASSERTDD (!(pContext->pCurrSS->dwSSFlags & SB_COMPRESSED),
"ERROR : StateSet compressed");
pContext->pCurrSS->uc.dwCurVertexShader = dwVtxShaderHandle;
pContext->pCurrSS->uc.dwFlags |= SB_CUR_VS_CHANGED;
}
} // _D3D_SB_Record_VertexShader_Set
//-----------------------------------------------------------------------------
//
// void _D3D_SB_Record_MStream_SetSrc
//
// Record this stream src set code into the current state set being recorded
//
//-----------------------------------------------------------------------------
void _D3D_SB_Record_MStream_SetSrc(P3_D3DCONTEXT* pContext,
DWORD dwStream,
DWORD dwVBHandle,
DWORD dwStride)
{
if (pContext->pCurrSS != NULL)
{
ASSERTDD (!(pContext->pCurrSS->dwSSFlags & SB_COMPRESSED),
"ERROR : StateSet compressed");
pContext->pCurrSS->uc.streamSource[dwStream].dwStream = dwStream;
pContext->pCurrSS->uc.streamSource[dwStream].dwVBHandle = dwVBHandle;
pContext->pCurrSS->uc.streamSource[dwStream].dwStride = dwStride;
pContext->pCurrSS->uc.dwFlags |= (SB_STREAMSRC_CHANGED << dwStream);
}
} // _D3D_SB_Record_MStream_SetSrc
//-----------------------------------------------------------------------------
//
// void _D3D_SB_Record_MStream_SetIndices
//
// Record this stream indices code into the current state set being recorded
//
//-----------------------------------------------------------------------------
void _D3D_SB_Record_MStream_SetIndices(P3_D3DCONTEXT* pContext,
DWORD dwVBHandle,
DWORD dwStride)
{
if (pContext->pCurrSS != NULL)
{
ASSERTDD (!(pContext->pCurrSS->dwSSFlags & SB_COMPRESSED),
"ERROR : StateSet compressed");
pContext->pCurrSS->uc.vertexIndex.dwVBHandle = dwVBHandle;
pContext->pCurrSS->uc.vertexIndex.dwStride = dwStride;
pContext->pCurrSS->uc.dwFlags |= SB_INDICES_CHANGED;
}
} // _D3D_SB_Record_MStream_SetIndices
#endif // DX8_MULTSTREAMS
//-----------------------------------------------------------------------------
//
// void _D3D_SB_Record_Viewport
//
// Record this viewport info into the current state set being recorded
//
//-----------------------------------------------------------------------------
void _D3D_SB_Record_Viewport(P3_D3DCONTEXT* pContext,
D3DHAL_DP2VIEWPORTINFO* lpvp)
{
if (pContext->pCurrSS != NULL)
{
ASSERTDD (!(pContext->pCurrSS->dwSSFlags & SB_COMPRESSED),
"ERROR : StateSet compressed");
pContext->pCurrSS->uc.viewport = *lpvp;
pContext->pCurrSS->uc.dwFlags |= SB_VIEWPORT_CHANGED;
}
} // _D3D_SB_Record_Viewport
//-----------------------------------------------------------------------------
//
// void _D3D_SB_Record_ZRange
//
// Record this z range info into the current state set being recorded
//
//-----------------------------------------------------------------------------
VOID _D3D_SB_Record_ZRange(P3_D3DCONTEXT* pContext,
D3DHAL_DP2ZRANGE* lpzr)
{
if (pContext->pCurrSS != NULL)
{
ASSERTDD (!(pContext->pCurrSS->dwSSFlags & SB_COMPRESSED),
"ERROR : StateSet compressed");
pContext->pCurrSS->uc.zRange = *lpzr;
pContext->pCurrSS->uc.dwFlags |= SB_ZRANGE_CHANGED;
}
}
#endif //DX7_D3DSTATEBLOCKS