/******************************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; juc.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; juc.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