📄 tautils.c
字号:
NB: must update the flags for the constants written, as we have
manually changed it flags
*/
FlagArrayUpdate((PFLAGARRAY)&sConstsWritten);
FlagArraySetFlags((PFLAGARRAY)psStateCtlConstsSetup,
(PFLAGARRAY)&sConstsWritten);
D3DM_DPF((DPF_EXIT, "<-TACSWriteVGPConstants"));
}
/*****************************************************************************
FUNCTION : TACSWriteVGPInstructions
PURPOSE : Writes VGP-instructions to the TA control-stream, updating
the context state-control data accordingly.
NB: This routine can write arbitrary instructions as specified
by the flags-array psInstsChanged. A single flag bit is
used for each instruction, arranged in increasing order
(LSB->MSB), with 32 instructions per DWORD of flags.
A set flag-bit indicates that the instruction should be
written. Only instructions specified in these flags-words
will be considered for writing.
Similar flags in the context state-control data (representing
the instructions that have been already written) are updated
to include the instructions actually sent to the HW. These
are maintained to indicate which instructions in the
context's 'current' hardware-state data are up-to-data and
thus valid. This routine will not sent instructions that are
identical to the current ones. Instructions that have not
been sent previously will always be sent.
This routine is fastest when sending small contiguous
groups of instructions. The slowest case is probably where
all instructions have been sent before and every-other
instruction is to be written - an unlikely case.
PARAMETERS : psContext - Current 3D rendering context
psInstsChanged - VGP-instruction flags indicating which
instructions are to be written
psNewInsts - HW state structure containing the new VGP
instruction data
bForceWrite - Control to force instructions to be written
even if they are the same as the current
instructions
RETURNS : void
*****************************************************************************/
void TACSWriteVGPInstructions(LPD3DM_CONTEXT psContext,
PVGPINSTFLAGS psInstsChanged,
PHWVGPCODE psNewInsts,
BOOL bForceWrite)
{
PHWVGPCODE psCurrInsts;
PHWSTATECTL psHWStateCtl;
DWORD pdwBlockData[(sizeof(HWVGPCODE)/sizeof(DWORD)) + 1];
PVGPINSTFLAGS psStateCtlInstsSetup;
PVGPINSTFLAGS psStateCtlInstsChanged;
VGPINSTFLAGS sInstsWritten;
PDWORD pdwDest;
DWORD dwLastInBlock;
DWORD i;
/*
Do nothing if no constants have changed
*/
if(!psInstsChanged->dwUsed)
{
D3DM_DPF((DPF_TA, "TACSWriteVGPInstructions: No flags set. Doing nothing"));
return;
}
psCurrInsts = &psContext->sCurrHWState.sVGPCode;
psHWStateCtl = &psContext->sHWStateCtl;
/*
psStateCtlInstsChanged - flag-words specifying the instructions
marked as changed from the context state-
control data
psStateCtlInstsSetup - flag-words specifying the instructions
marked as previously setup (i.e. submitted
to the HW) from the context state-control
data
psInstsWritten - flag-words indicating which instructions we
need to write
*/
psStateCtlInstsChanged = &psHWStateCtl->sVGPInstsChanged;
psStateCtlInstsSetup = &psHWStateCtl->sVGPInstsSetup;
sInstsWritten = *psInstsChanged;
/*
If forcing the state to be output, remove the new instructions from
the instructions already setup. This disables the comparison between
the new and current values for them, so that they always gets written.
*/
if(bForceWrite)
{
FlagArrayClearFlags((PFLAGARRAY)psStateCtlInstsSetup,
(PFLAGARRAY)psInstsChanged);
}
/*
Initialise the block-data pointer ready to start a new block of
instructions - remembering to leave a DWORD for the header.
*/
pdwDest = &pdwBlockData[1];
/*
Initialise the last instruction in the current block to ensures that
the current block (which will be empty) is not written when the first
instruction is added to it.
*/
dwLastInBlock = MBX1_VGPCODE_INST_COUNT;
/*
Loop through all instructions, adding those that need to be written to
the instruction-block data
*/
for(i = 0; i < (MBX1_VGPCODE_INST_COUNT/(sizeof(DWORD)*8)); i++)
{
DWORD dwSetup;
DWORD dwLeft;
DWORD dwFlag;
DWORD dwInstNum;
/*
Skip this group of instructions if we have none to process in it
*/
dwLeft = psInstsChanged->pdwFlags[i];
if(!dwLeft)
{
continue;
}
dwSetup = psStateCtlInstsSetup->pdwFlags[i];
/*
Process this group of instructions until we have handled all the
changed ones.
*/
for(dwInstNum = i<<5, dwFlag = 0x1UL; dwLeft; dwFlag <<= 1, dwInstNum++)
{
PHWVGPINST psNewInst;
PHWVGPINST psCurrInst;
/*
Skip instruction if it hasn't changed
*/
if(!(dwLeft & dwFlag))
{
continue;
}
/*
Is the new value different from the current (if any)?
*/
psCurrInst = &psCurrInsts->psInsts[dwInstNum];
psNewInst = &psNewInsts->psInsts[dwInstNum];
if(!(dwSetup & dwFlag) ||
(psNewInst->word.dwLo ^ psCurrInst->word.dwLo) ||
(psNewInst->word.dwHi ^ psCurrInst->word.dwHi))
{
D3DM_DPF((DPF_TA, "TACSWriteVGPInstructions: Instruction %d changed. Including in block", dwInstNum));
/*
Instruction changed or never written before. Must write.
If the new instruction is not contiguous with those already
copied into the current instruction-block, we cannot add it
to that block. Must write the current block of instructions
and start a new-one.
*/
if (dwInstNum > (dwLastInBlock + 1))
{
DWORD dwFirstInBlock;
DWORD dwDataSize;
/* Determine the range of constants in this block */
dwDataSize = (pdwDest - pdwBlockData - 1) * sizeof(DWORD);
dwFirstInBlock = dwLastInBlock - (dwDataSize/sizeof(HWVGPINST) - 1);
/* Add header to start of block */
pdwBlockData[0] = MBX1_TAOBJTYPE_VGP_CODE |
(dwFirstInBlock << MBX1_VGPCODE_STARTADDR_SHIFT) |
(dwLastInBlock << MBX1_VGPCODE_ENDADDR_SHIFT);
dwDataSize += sizeof(DWORD);
/* Output the block-data */
DBG_DECODEVGPCODEBLOCK(psContext, pdwBlockData);
TACSWriteData(psContext, pdwBlockData, dwDataSize);
/*
Reset the block-data pointer ready to start a new
block of instructions - remembering to leave a DWORD
for the header.
*/
pdwDest = &pdwBlockData[1];
/*
Initialise the last instruction in the current block
to ensures that the current block (which will be
empty) is not written when the first instruction is
added to it.
*/
dwLastInBlock = MBX1_VGPCODE_INST_COUNT;
}
/*
Add this instruction to the current instruction-block
*/
*(PHWVGPINST)pdwDest = *psNewInst;
*psCurrInst = *psNewInst;
pdwDest += sizeof(HWVGPINST) / sizeof(DWORD);
/*
Record that this instruction is the last one in the
current block of instructions to write
*/
dwLastInBlock = dwInstNum;
}
else
{
D3DM_DPF((DPF_TA, "TACSWriteVGPInstructions: Instruction %d unchanged", dwInstNum));
/*
Same as current. Remove from constants written
*/
sInstsWritten.pdwFlags[i] ^= dwFlag;
}
/*
Remove this instruction from the ones left to handle
*/
dwLeft ^= dwFlag;
}
}
/*
Write the final block of instructions (if any)
*/
if (dwLastInBlock < MBX1_VGPCODE_INST_COUNT)
{
DWORD dwFirstInBlock;
DWORD dwDataSize;
/*
Determine the range of constants in this block
*/
dwDataSize = (pdwDest - pdwBlockData - 1) * sizeof(DWORD);
dwFirstInBlock = dwLastInBlock - (dwDataSize/sizeof(HWVGPINST) - 1);
/* Add header to start of block */
pdwBlockData[0] = MBX1_TAOBJTYPE_VGP_CODE |
(dwFirstInBlock << MBX1_VGPCODE_STARTADDR_SHIFT) |
(dwLastInBlock << MBX1_VGPCODE_ENDADDR_SHIFT);
dwDataSize += sizeof(DWORD);
/* Output the block-data */
DBG_DECODEVGPCODEBLOCK(psContext, pdwBlockData);
TACSWriteData(psContext, pdwBlockData, dwDataSize);
}
/*
Record which instructions we have just written-out
NB: must update the flags for the instructions written, as we have
manually changed it's flags
*/
FlagArrayUpdate((PFLAGARRAY)&sInstsWritten);
FlagArraySetFlags((PFLAGARRAY)psStateCtlInstsSetup,
(PFLAGARRAY)&sInstsWritten);
}
/*****************************************************************************
FUNCTION : UpdateVGPInstructions
PURPOSE : Updates the VGP-code required for the next primitive, and
submits any changes to the HW.
PARAMETERS : psContext - Current 3D rendering context
RETURNS : void
*****************************************************************************/
IMG_VOID UpdateVGPInstructions(LPD3DM_CONTEXT psContext)
{
PHWSTATECTL psHWStateCtl;
PVGPINSTFLAGS psInstsChanged;
psHWStateCtl = &psContext->sHWStateCtl;
/*
Any constants in this bank changed?
*/
psInstsChanged = &psHWStateCtl->sVGPInstsChanged;
if(psInstsChanged->dwUsed)
{
PHWVGPCODE psNewInsts;
D3DM_DPF((DPF_TA, "UpdateVGPInstructions: updating instructions"));
/*
Submit the changed instructions (only written if different
to current values)
*/
psNewInsts = &psContext->sHWState.sVGPCode;
TACSWriteVGPInstructions(psContext,
psInstsChanged,
psNewInsts,
FALSE);
/*
Reset the instruction 'state-changed' flags (since all changed
instructions have been output)
*/
FlagArrayClearFlagRange((PFLAGARRAY)psInstsChanged,
0,
psInstsChanged->dwSize - 1);
}
}
#endif /* SUPPORT_VGP */
/*********************************************************************************
End of VGP Specific
*********************************************************************************/
/*********************************************************************************
Function : TACSWriteData
Description : Low-level routine to output a given block of data to the
TA control-stream slave port.
Parameters : psContext - Current 3D rendering context
pvData - The data to write
dwDataSize - The amount of data to write (in bytes)
Return : void
*********************************************************************************/
void TACSWriteData(LPD3DM_CONTEXT psContext, PVOID pvData, DWORD dwDataSize)
{
PVRSRV_DEV_INFO *psDevInfo;
PVRSRV_DEV_DATA *psDevData;
PVRSRV_DEV_LOCATION *psDevLoc;
DWORD dwDataLeft;
PVOID *pvRegBase;
DWORD *pdwData;
DWORD dwBytesObtained = 0;
DWORD dwAmountToWrite;
D3DM_DPF((DPF_ENTRY, "->TACSWriteData"));
PROFILE_START_FUNC(TACS_WRITE_DATA);
psDevData = &psContext->sDevData;
psDevInfo = GetDevInfo(psContext);
pvRegBase = GetRegisterBase(psContext);
psDevLoc = &psDevInfo->sDevLocation;
/* convert from bytes to DWORDs */
dwDataLeft = (dwDataSize + 3) >> 2;
pdwData = (DWORD*)pvData;
while(dwDataLeft)
{
/* Obtain available fifo space if we have none */
if(psContext->dwAllocatedFifoSpaceDWORDS == 0)
{
PVRSRVAcquire3DFifoSpace (psDevData->psDevInfoUM,
&psContext->sHWInfo,
&dwBytesObtained);
psContext->dwAllocatedFifoSpaceDWORDS = dwBytesObtained >> 2;
}
/* Calculate how many DWORDs we should write */
if(psContext->dwAllocatedFifoSpaceDWORDS > dwDataLeft)
{
dwAmountToWrite = dwDataLeft;
}
else
{
dwAmountToWrite = psContext->dwAllocatedFifoSpaceDWORDS;
}
D3DM_DPF((DPF_TA, "TACSWriteData: Writing %d bytes from 0x%8.8lX", (dwAmountToWrite <<2), pvData));
/* Batch write as much data as we can*/
PVRSRVWriteSlavePortBatch(&psContext->sHWInfo.sDeviceSpecific.sMBX.sTASlavePort,
pdwData,
(dwAmountToWrite<<2));
dwDataLeft -= dwAmountToWrite;
psContext->dwAllocatedFifoSpaceDWORDS -= dwAmountToWrite;
PVRSRVRelease3DFifoSpace(psDevData->psDevInfoUM, (dwAmountToWrite << 2));
/* Dump SP writes */
PDUMPSPBATCH(psContext->psPDContext, PDUMPTAGS_SP_MBX_DATA, pdwData, dwAmountToWrite);
/* Update our data pointer */
pdwData += dwAmountToWrite;
}
/* Signal that we've sent some data to the TA */
psContext->psCurrentRenderTarget->sDescription.sSurface.bSceneTADataSent = TRUE;
D3DM_DPF((DPF_EXIT, "<-TACSWriteData"));
PROFILE_STOP_FUNC(TACS_WRITE_DATA);
}
/*********************************************************************************
Function : TACSWriteTermDWORD
Description : Low-level routine to write a DWORD to the slave-port terminate
address
Parameters : psContext - Current 3D rendering context
dwValue - The value to write
Return : void
*********************************************************************************/
void TACSWriteTermDWORD(LPD3DM_CONTEXT psContext, DWORD dwValue)
{
PVRSRV_DEV_INFO *psDevInfo;
PVRSRV_DEV_DATA *psDevData;
PVRSRV_DEV_LOCATION *psDevLoc;
PVOID *pvRegBase;
DWORD dwBytesObtained;
D3DM_DPF((DPF_ENTRY, "->TACSWriteTACtlAnd3DState"));
PROFILE_START_FUNC(TACS_WRITE_TERM_DWORD);
psDevData = &psContext->sDevData;
psDevInfo = GetDevInfo(psContext);
pvRegBase = GetRegisterBase(psContext);
psDevLoc = &psDevInfo->sDevLocation;
dwBytesObtained = 0;
/* Aquire FIFO space if required */
if(psContext->dwAllocatedFifoSpaceDWORDS == 0)
{
while(!dwBytesObtained)
{
PVRSRVAcquire3DFifoSpace (psDevData->psDevInfoUM,
&psContext->sHWInfo,
&dwBytesObtained);
}
psContext->dwAllocatedFifoSpaceDWORDS = dwBytesObtained >> 2;
}
/* Write the DWORD and update space count */
PVRSRVWriteSlavePort(&psContext->sHWInfo.sDeviceSpecific.sMBX.sTAControlSlavePort, dwValue);
psContext->dwAllocatedFifoSpaceDWORDS--;
PVRSRVRelease3DFifoSpace(psDevData->psDevInfoUM, 4 /*bytes*/);
/* Pdump SP Dword write */
PDUMPSP(psContext->psPDContext, PDUMPTAGS_SP_MBX_TERM, dwValue);
PROFILE_STOP_FUNC(TACS_WRITE_TERM_DWORD);
}
/*****************************************************************************
End of file (tautils)
*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -