📄 tautils.c
字号:
TACSWriteVGPControlState(psContext,
dwStateChanged,
psNewVGPControlState,
FALSE);
/*
Reset the VGP-control 'state-changed' flags (since all changed
state has now been output)
*/
psHWStateCtl->dwVGPCtlStateChanged = 0;
D3DM_DPF((DPF_EXIT, "<-UpdateVGPControlState"));
}
/*****************************************************************************
FUNCTION : UpdateVGPConstants
PURPOSE : Updates the VGP-constants required for the next primitive, and
submits any changes to the HW.
PARAMETERS : psContext - Current 3D rendering context
RETURNS : void
*****************************************************************************/
void UpdateVGPConstants(LPD3DM_CONTEXT psContext)
{
PVGPCONSTFLAGS psConstsChanged;
PHWSTATECTL psHWStateCtl;
D3DM_DPF((DPF_ENTRY, "->UpdateVGPConstants"));
psHWStateCtl = &psContext->sHWStateCtl;
/* Any constants in this bank changed? */
psConstsChanged = &psHWStateCtl->sVGPConstsChanged;
if(psConstsChanged->dwUsed)
{
PHWVGPCONSTANTS psNewConsts;
D3DM_DPF((DPF_TA, "UpdateVGPConstants: updating constants"));
/*
Submit the changed constants (only written if different to
current values)
*/
psNewConsts = &psContext->sHWState.sVGPConsts;
TACSWriteVGPConstants(psContext,
psConstsChanged,
psNewConsts,
FALSE);
/*
Reset the constant 'state-changed' flags (since all changed
constants have been output)
*/
FlagArrayClearFlagRange((PFLAGARRAY)psConstsChanged,
0,
psConstsChanged->dwSize - 1);
}
else
{
D3DM_DPF((DPF_TA, "UpdateVGPConstants: No constants changed."));
}
D3DM_DPF((DPF_EXIT, "<-UpdateVGPConstants"));
}
/*****************************************************************************
FUNCTION : TACSWriteVGPControlState
PURPOSE : Writes a VGP-control block to the TA control stream
PARAMETERS : psContext - Current 3D rendering context
dwStateChanged - Section-definition presence flags indicating
which definitions are to be written (see
MBX1_VGPCONTROL_SECTIONxDEF_ENABLE flags)
psNewVGPControl - HW-state structure containing the new
section-definitions to be written
bForceWrite - Control to force state to be written
even if it is the same as the current
state-data.
RETURNS : void
*****************************************************************************/
void TACSWriteVGPControlState(LPD3DM_CONTEXT psContext,
DWORD dwStateChanged,
PHWVGPCONTROL psNewVGPControl,
BOOL bForceWrite)
{
PHWVGPCONTROL psCurrVGPControl;
PHWSTATECTL psHWStateCtl;
PDWORD pdwNewSectionDef;
PDWORD pdwCurrSectionDef;
DWORD pdwBlockData[(sizeof(HWVGPCONTROL)/sizeof(DWORD)) + 1];
DWORD dwStateSetup;
DWORD dwStateLeft;
DWORD dwStateToWrite;
PDWORD pdwDest;
DWORD i;
D3DM_DPF((DPF_ENTRY, "->TACSWriteVGPControlState")
/* Do nothing if no section definitions are present */
dwStateChanged &= ~MBX1_VGPCONTROL_SECTIONENABLECLRMASK;
if(!dwStateChanged)
{
D3DM_DPF((DPF_TA, "TACSWriteVGPControlState: No flags set. Doing nothing"));
return;
}
D3DM_DPF((DPF_TA, "TACSWriteVGPControlState: flags 0x%8.8lX", dwStateChanged));
psCurrVGPControl = &psContext->sCurrHWState.sVGPControl;
psHWStateCtl = &psContext->sHWStateCtl;
/*
dwStateSetup - which state has already been setup
dwStateToWrite - which state we may need to write
dwStateLeft - which state we still have to process
*/
dwStateSetup = psHWStateCtl->dwVGPCtlStateSetup &
(~MBX1_VGPCONTROL_SECTIONENABLECLRMASK);
dwStateToWrite = dwStateChanged;
dwStateLeft = dwStateChanged;
/*
If forcing the state to be output, remove the new state from the
state already setup. This disables the comparison between the new
and current values for this state, so that it always gets written.
*/
if(bForceWrite)
{
dwStateSetup &= ~dwStateChanged;
}
/* Leave the first DWORD in the block-data free for the header */
pdwDest = &pdwBlockData[1];
/*
Loop through all section-definitions, adding those that need to be
written to the state-block data
*/
pdwNewSectionDef = psNewVGPControl->pdwSectionDef;
pdwCurrSectionDef = psCurrVGPControl->pdwSectionDef;
for(i = 0; i < MBX1_VGPCODE_SECTION_COUNT; i++)
{
DWORD dwSectionPresFlag;
/* Include this section-definition? */
dwSectionPresFlag = MBX1_VGPCONTROL_SECTION0DEF_ENABLE << i;
if(dwStateLeft & dwSectionPresFlag)
{
/* Is the new value different from the current (if any)? */
if((!(dwStateSetup & dwSectionPresFlag)) || (*pdwNewSectionDef ^ *pdwCurrSectionDef))
{
D3DM_DPF((DPF_TA, "TACSWriteVGPControlState: VGP section-def %d changed. Including in block", i));
/* Changed or never written before. Add to state-block */
*pdwDest = *pdwNewSectionDef;
*pdwCurrSectionDef = *pdwNewSectionDef;
pdwDest++;
}
else
{
D3DM_DPF((DPF_TA, "TACSWriteVGPControlState: VGP section-def %d unchanged. Removing from block", i));
/* Same as current. Remove from state to write */
dwStateToWrite ^= dwSectionPresFlag;
}
/* Write the state-block if we have handled all the changed state now */
dwStateLeft ^= dwSectionPresFlag;
if(!dwStateLeft)
{
break;
}
}
/* Move to next section-definition */
pdwNewSectionDef++;
pdwCurrSectionDef++;
}
/* If we have some state to write, do so */
if(dwStateToWrite)
{
DWORD dwBlockSize;
D3DM_DPF((DPF_TA, "TACSWriteVGPControlState: Writing block with flags 0x%8.8lX", dwStateToWrite));
/* Add header to start of block */
pdwBlockData[0] = MBX1_TAOBJTYPE_VGP_CONTROL | dwStateToWrite;
/* Output the block */
DBG_DECODEVGPCONTROLBLOCK(psContext, pdwBlockData);
dwBlockSize = (pdwDest - pdwBlockData) * sizeof(DWORD);
TACSWriteData(psContext, pdwBlockData, dwBlockSize);
}
/* Record which state we have written */
psHWStateCtl->dwVGPCtlStateSetup |= dwStateToWrite;
D3DM_DPF((DPF_EXIT, "<-TACSWriteVGPControlState"));
}
/*****************************************************************************
FUNCTION : TACSWriteVGPConstants
PURPOSE : Writes VGP-constants to the TA control-stream, updating the
context state-control data accordingly.
NB: This routine can write arbitrary constants as specified
by the flags-array psConstsChanged. A single flag bit is
used for each constant, arranged in increasing order
(LSB->MSB), with 32 constants per DWORD of flags. A set
flag-bit indicates that the constant should be written.
Only constants specified in these flags-words will be
considered for writing.
Similar flags in the context state-control data (representing
the constants that have been already written) are updated to
include the constants actually sent to the HW. These are
maintained to indicate which constants in the context's
'current' hardware-state data are up-to-data and thus
valid. This routine will not sent constant where the new
value is identical to the current. Constants that have not
been sent previously will always be sent.
This routine is fastest when sending small contiguous
groups of constants. The slowest case is probably where
all constants have been sent before and every-other
constant is to be written - an unlikely case.
PARAMETERS : psContext - Current 3D rendering context
psConstsChanged - VGP-constant flags indicating which constants
are to be written
psNewConsts - HW state structure containing the new VGP
constant data
bForceWrite - Control to force constants to be written
even if they are the same as the current
constants.
RETURNS : void
*****************************************************************************/
void TACSWriteVGPConstants(LPD3DM_CONTEXT psContext,
PVGPCONSTFLAGS psConstsChanged,
PHWVGPCONSTANTS psNewConsts,
BOOL bForceWrite)
{
PHWVGPCONSTANTS psCurrConsts;
PHWSTATECTL psHWStateCtl;
DWORD pdwBlockData[(sizeof(HWVGPCONSTANTS)/sizeof(DWORD)) + 1];
PVGPCONSTFLAGS psStateCtlConstsSetup;
VGPCONSTFLAGS sConstsWritten;
PDWORD pdwDest;
DWORD dwLastInBlock;
DWORD i;
D3DM_DPF((DPF_ENTRY, "->TACSWriteVGPConstants"));
/* Do nothing if no constants have changed */
if(!psConstsChanged->dwUsed)
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: No flags set. Doing nothing"));
return;
}
#if defined(DEBUG)
for(i = 0; i < (MBX1_VGPCONSTANTS_CONST_COUNT/(sizeof(DWORD)*8)); i++)
{
if(psConstsChanged->dwUsed & (1L << i))
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: constants %d-%d changed: 0x%8.8lX", i*32, i*32+31, psConstsChanged->pdwFlags[i]));
}
}
#endif /* #if defined(DEBUG) */
psCurrConsts = &psContext->sCurrHWState.sVGPConsts;
psHWStateCtl = &psContext->sHWStateCtl;
/*
psStateCtlConstsSetup - flag-words specifying the constants marked
as previously setup (i.e. submitted to the
HW) from the context state-control data
sConstsWritten - flag-words indicating which constants we
need to write
*/
psStateCtlConstsSetup = &psHWStateCtl->sVGPConstsSetup;
sConstsWritten = *psConstsChanged;
/*
If forcing the state to be output, remove the new constants from
the constants already setup. This disables the comparison between the
new and current values for them, so that they always gets written.
*/
if(bForceWrite)
{
FlagArrayClearFlags((PFLAGARRAY)psStateCtlConstsSetup,
(PFLAGARRAY)psConstsChanged);
}
/*
Initialise the block-data pointer ready to start a new block of
constants - remembering to leave a DWORD for the header.
*/
pdwDest = &pdwBlockData[1];
/*
Initialise the last constant in the current block to ensures that
the current block (which will be empty) is not written when the
first constant is added to it.
*/
dwLastInBlock = MBX1_VGPCONSTANTS_CONST_COUNT;
/*
Loop through all constants, adding those that need to be written to
the constant-block data
*/
for(i = 0; i < (MBX1_VGPCONSTANTS_CONST_COUNT/(sizeof(DWORD)*8)); i++)
{
DWORD dwSetup;
DWORD dwLeft;
DWORD dwFlag;
DWORD dwConstNum;
/* Skip this group of constants if we have none to process in it */
dwLeft = psConstsChanged->pdwFlags[i];
if(!dwLeft)
{
continue;
}
dwSetup = psStateCtlConstsSetup->pdwFlags[i];
/*
Process this group of constants until we have handled all the
changed ones.
*/
dwConstNum = i << 5;
for (dwFlag = 0x1UL; dwLeft; dwFlag <<= 1, dwConstNum++)
{
PHWVGPCONST psNewConst;
PHWVGPCONST psCurrConst;
/*
Has this constant changed?
*/
if(dwLeft & dwFlag)
{
/* Is the new value different from the current (if any)? */
psCurrConst = &psCurrConsts->psConsts[dwConstNum];
psNewConst = &psNewConsts->psConsts[dwConstNum];
if((!(dwSetup & dwFlag)) ||
(psNewConst->e[0].dwVal ^ psCurrConst->e[0].dwVal) ||
(psNewConst->e[1].dwVal ^ psCurrConst->e[1].dwVal) ||
(psNewConst->e[2].dwVal ^ psCurrConst->e[2].dwVal) ||
(psNewConst->e[3].dwVal ^ psCurrConst->e[3].dwVal))
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: Constant %d changed. Including in block", dwConstNum));
/*
Constant changed or never written before. Must write.
If the new constant is not contiguous with those already
copied into the current constant-block, we cannot add it
to that block. Must write the current block of constants
and start a new-one.
*/
if(dwConstNum > (dwLastInBlock + 1))
{
DWORD dwFirstInBlock;
DWORD dwDataSize;
/*
Determine the range of constants in this block
*/
dwDataSize = (pdwDest - pdwBlockData - 1) * sizeof(DWORD);
dwFirstInBlock = dwLastInBlock - (dwDataSize/sizeof(HWVGPCONST) - 1);
#if defined(DEBUG)
if (dwFirstInBlock == dwLastInBlock)
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: Writing constant %d", dwFirstInBlock));
}
else
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: Writing constants %d to %d", dwFirstInBlock, dwLastInBlock));
}
#endif /* #if defined(DEBUG) */
/* Add header to start of block */
pdwBlockData[0] = MBX1_TAOBJTYPE_VGP_CONSTANTS |
(dwFirstInBlock << MBX1_VGPCONSTANTS_STARTADDR_SHIFT) |
(dwLastInBlock << MBX1_VGPCONSTANTS_ENDADDR_SHIFT);
dwDataSize += sizeof(DWORD);
/* Output the block-data */
DBG_DECODEVGPCONSTANTSBLOCK(psContext, pdwBlockData);
TACSWriteData(psContext, pdwBlockData, dwDataSize);
/*
Reset the block-data pointer ready to start a new
block of constants - remembering to leave a DWORD
for the header.
*/
pdwDest = &pdwBlockData[1];
/*
Initialise the last constant in the current block
to ensures that the current block (which will be
empty) is not written when the first constant is
added to it.
*/
dwLastInBlock = MBX1_VGPCONSTANTS_CONST_COUNT;
}
/* Add this constant to the current constant-block */
*(PHWVGPCONST)pdwDest = *psNewConst;
*psCurrConst = *psNewConst;
pdwDest += sizeof(HWVGPCONST) / sizeof(DWORD);
/*
Record that this constant is the last one in the current
block of constants to write
*/
dwLastInBlock = dwConstNum;
}
else
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: Constant %d unchanged", dwConstNum));
/* Same as current. Remove from constants written */
sConstsWritten.pdwFlags[i] ^= dwFlag;
}
/* Remove this constant from the ones left to handle */
dwLeft ^= dwFlag;
}
}
}
/* Write the final block of constants (if any) */
if(dwLastInBlock < MBX1_VGPCONSTANTS_CONST_COUNT)
{
DWORD dwFirstInBlock;
DWORD dwDataSize;
/* Determine the range of constants in this block */
dwDataSize = (pdwDest - pdwBlockData - 1) * sizeof(DWORD);
dwFirstInBlock = dwLastInBlock - (dwDataSize/sizeof(HWVGPCONST) - 1);
#if defined(DEBUG)
if(dwFirstInBlock == dwLastInBlock)
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: Writing constant %d", dwFirstInBlock));
}
else
{
D3DM_DPF((DPF_TA, "TACSWriteVGPConstants: Writing constants %d to %d", dwFirstInBlock, dwLastInBlock));
}
#endif /* #if defined(DEBUG) */
/* Add header to start of block */
pdwBlockData[0] = MBX1_TAOBJTYPE_VGP_CONSTANTS |
(dwFirstInBlock << MBX1_VGPCONSTANTS_STARTADDR_SHIFT) |
(dwLastInBlock << MBX1_VGPCONSTANTS_ENDADDR_SHIFT);
dwDataSize += sizeof(DWORD);
/* Output the block-data */
DBG_DECODEVGPCONSTANTSBLOCK(psContext, pdwBlockData);
TACSWriteData(psContext, pdwBlockData, dwDataSize);
}
/*
Record which constants we have just written-out
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -