📄 complexscene.c
字号:
}
}
#endif
/*!
******************************************************************************
@Function PVRSRVComplexScene
@Description
complex scene management.
@Input psDevInfo - device info. structure
@Input psRenderCmd - render command
@Return none
******************************************************************************/
IMG_VOID PVRSRVComplexScene (PVRSRV_DEV_INFO *psDevInfo, PVRSRV_RENDER_CMD_INFO *psRenderCmd)
{
DEVICE3D *ps3D = &psDevInfo->sDeviceSpecific.s3D;
IMG_PVOID pvRegsBase = psDevInfo->sDevLocation.pvRegsBaseKM;
PVR3DIF_3DCTL *ps3DCtl = (PVR3DIF_3DCTL*)psRenderCmd->psTARenderInfo->psSharedData;
IMG_UINT32 ui32CurrentRenderData = ps3DCtl->sSharedData.ui32CurrentRenderData;
IMG_VOID *pvRHBase = ps3DCtl->apvRgnHeadersKM[ui32CurrentRenderData];
PVRSRV_HWREG *ps3DRegs = (PVRSRV_HWREG*)psRenderCmd->aui32Data;
PVRSRV_HWREG *psZLSCtrlReg = IMG_NULL;
PMBX1_REGION_ENTRY psRegionHdr;
PPVR_CS_INFO psCSInfo;
IMG_DEV_VIRTADDR RHDevAddr = ps3DCtl->sSharedData.asRgnHeaderDevVAddr[ui32CurrentRenderData];
volatile IMG_UINT32 vui32IStatus = 0;
IMG_UINT32 ui32XMTile, ui32YMTile, ui32XTilesPerMT, ui32YTilesPerMT;
IMG_UINT32 ui32XMTiles, ui32RHOffset, ui32ZLSBits, i;
#if defined(FIX_HW_PRN_264_MBX) || defined(FIX_HW_PRN_264_MBXLITE)
IMG_BOOL bFirstRenderInScene = (ps3DCtl->psCSInfoKM == IMG_NULL ? IMG_TRUE : IMG_FALSE);
#endif
/*
Find MBX1_GLOBREG_ZLOADSTORE
*/
for(i=0; i<psRenderCmd->ui32RegCount; i++)
{
if(ps3DRegs[i].ui32RegAddr == MBX1_GLOBREG_ZLOADSTORE)
{
psZLSCtrlReg = &ps3DRegs[i];
break;
}
}
PVR_ASSERT (psZLSCtrlReg);
#ifdef SUPPORT_MBX1
/*
read back tile to abort but first wait for valid bit to be set
*/
do
{
vui32IStatus = ReadHWReg(pvRegsBase, MBX1_GLOBREG_INT_STATUS);
} while((vui32IStatus & MBX1_INT_TA_MT_VALID) == 0);
#endif
/*
(I assume TA interrupts are disabled here)
Abort the TA on given MT
*/
ui32XMTile = (vui32IStatus & MBX1_INT_TA_MACTILEX_MASK)
>> MBX1_INT_TA_MACTILEX_SHIFT;
ui32YMTile = (vui32IStatus & MBX1_INT_TA_MACTILEY_MASK)
>> MBX1_INT_TA_MACTILEY_SHIFT;
WriteHWReg ( pvRegsBase,
MBX1_TAGLOBREG_ABORTXY,
(ui32XMTile<<MBX1_TA_ABORTX_SHIFT) |
(ui32YMTile<<MBX1_TA_ABORTY_SHIFT) );
WriteHWReg (pvRegsBase, MBX1_TAGLOBREG_ABORT, 1);
ui32XMTiles = ps3DCtl->sSharedData.ui32MTilesX;
/*
need to do a bit of Region Header jiggery pokery
(we'll poll for the TA abort(complete) interrupt later)
*/
ui32XTilesPerMT = ps3DCtl->sSharedData.ui32XTilesPerMT;
ui32YTilesPerMT = ps3DCtl->sSharedData.ui32YTilesPerMT;
/*
MTs are in scan order and RHs are in scan order within each MT
Zbuffer is just scan order
*/
/* RH offset to MT (8bytes/RH) */
ui32RHOffset = ((ui32YMTile * ui32XMTiles) + ui32XMTile) * ui32XTilesPerMT * ui32YTilesPerMT * 8;
psRegionHdr = (PMBX1_REGION_ENTRY)((IMG_UINT32)pvRHBase + ui32RHOffset);
/*
Poll for TA_COMPLETE from previous TA abort
n.b. shouldn't have to wait any time for the interrupt.
If not acceptable then we need to special case
TA complete int handler
*/
//FIXME: need delay here!
for (i=0; i<100000; i++)
{
vui32IStatus = ReadHWReg(pvRegsBase, MBX1_GLOBREG_INT_STATUS);
if ((vui32IStatus & MBX1_INT_TA_COMPLETE) == MBX1_INT_TA_COMPLETE)
{
break;
}
}
if (i==100000)
{
for (i=0; i<100000; i++)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVComplexScene: failed TA abort"));
PVR_DPF((PVR_DBG_ERROR,"FIXME: what to do about it?"));
}
}
SysClearDeviceInterrupts (psDevInfo, pvRegsBase, MBX1_INT_TA_COMPLETE);
/*
Z load/store controls for region headers and ZLOADSTORE register
are derived from:
Z = "Z buffer present?"
P = "Was there a previous partial render to this macrotile?"
*/
ui32ZLSBits = 0;
/*
Check for a previous partial render to this macrotile in linked list
of CSInfo structures. If there was one, we will need to do a ZLOAD.
*/
psCSInfo = ps3DCtl->psCSInfoKM;
while(psCSInfo)
{
if(psCSInfo->psRegionHdr == psRegionHdr)
{
ui32ZLSBits |= MBX1_RH_ZLOAD;
psZLSCtrlReg->ui32RegVal |= MBX1_ZLOADSTORE_ZLOAD;
break;
}
psCSInfo = psCSInfo->psNext;
}
/*
Check for an external Z buffer.
*/
if(psRenderCmd->bExternalDepthBuffer)
{
/*
We have an external Z buffer, so do a ZSTORE.
*/
ui32ZLSBits |= MBX1_RH_ZSTORE;
psZLSCtrlReg->ui32RegVal |= MBX1_ZLOADSTORE_ZSTORE
| ((ps3DCtl->sSharedData.ui32TilesX-1)<<MBX1_ZLOADSTORE_XEXTENTSHIFT);
/*
Clear no Zbuffer bit
*/
psZLSCtrlReg->ui32RegVal &= ~MBX1_ZLOADSTORE_ZFORMAT_NO_EXT_Z;
}
else
{
/*
OK, we have no external ZBuffer, use the special Zload mode
to initialise the internal Z buffer, with the value used in
the last clear. This will only be done if there was a previous
partial render to this macrotile.
*/
psZLSCtrlReg->ui32RegVal |= MBX1_ZLOADSTORE_ZFORMAT_NO_EXT_Z;
/*
tell client to allocate a DepthBuffer when it gets a chance
*/
ps3DCtl->sSharedData.bAllocateDepthbuffer = IMG_TRUE;
}
/*
Modify the RHs to do a store/load
*/
for(i=0; i<ui32XTilesPerMT*ui32YTilesPerMT; i++)
{
psRegionHdr[i].ui32Header |= ui32ZLSBits;
}
#if defined(FIX_HW_PRN_264_MBX)
if(bFirstRenderInScene)
{
ps3D->ui32TAConfigRegVal = ReadHWReg (pvRegsBase, MBX1_TAGLOBREG_CONFIG);
WriteHWReg ( pvRegsBase, MBX1_TAGLOBREG_CONFIG, ps3D->ui32TAConfigRegVal | MBX1_TACONFIG_NO_INITIALISE );
}
else
{
ContextStoreLoad(psDevInfo, ps3D);
/* Don't do this on first partial render for this macrotile (will already be covered by SW BG Obj) */
if(psCSInfo)
{
InsertOpaqueObjectTPC( ps3D, ps3DCtl,
psCSInfo->ui32MacroTileXOffsetInTiles,
psCSInfo->ui32MacroTileYOffsetInTiles);
}
ClearTPC(ps3D, ps3DCtl, ui32XMTile * ui32XTilesPerMT, ui32YMTile * ui32YTilesPerMT);
}
#elif defined(FIX_HW_PRN_264_MBXLITE)
/* Don't do this on first render in scene (will already be covered by SW BG Obj) */
if(!bFirstRenderInScene)
{
InsertOpaqueObject(ps3D, psRegionHdr, ui32XTilesPerMT, ui32YTilesPerMT);
}
#endif
#if defined(FIX_HW_PRN_223) || defined(FIX_HW_PRN_251)
/* Don't do this on first partial render for this macrotile (will already be covered by SW BG Obj) */
if(psCSInfo)
AddCoveredLastTile(ps3D, ps3DCtl, psRegionHdr, IMG_TRUE);
#endif
/* Only for MBX - does it matter? */
psRegionHdr[ui32XTilesPerMT*ui32YTilesPerMT-1].ui32Header |= MBX1_RH_LAST_IN_FRAME;
/*
Add ZStore to a linked list for this context
if we haven't already:
uRHOffset of MT to ZStore
ui32XTilesPerMT/Height
*/
if((ui32ZLSBits & MBX1_RH_ZLOAD)==0)
{
psCSInfo = &ps3DCtl->psCSInfoMemKM[ui32XMTile + (ui32YMTile * ui32XMTiles)];
#if defined (FIX_HW_PRN_264_MBX)
psCSInfo->ui32MacroTileXOffsetInTiles = ui32XMTile * ui32XTilesPerMT;
psCSInfo->ui32MacroTileYOffsetInTiles = ui32YMTile * ui32YTilesPerMT;
#endif
psCSInfo->psRegionHdr = psRegionHdr;
psCSInfo->RgnHeaderDevVAddr.uiAddr = RHDevAddr.uiAddr + ui32RHOffset;
/* put in the head of the list */
psCSInfo->psNext = ps3DCtl->psCSInfoKM;
ps3DCtl->psCSInfoKM = psCSInfo;
}
/*
make sure we don't deallocate the global list
*/
WriteHWReg ( pvRegsBase,
MBX1_TAGLOBREG_GLOBAL_LIST_CTRL,
MBX1_TA_GLOBAL_LIST_CTRL_OBJSIZE_MASK);
ps3D->ui32TAConfigRegVal = ReadHWReg (pvRegsBase, MBX1_TAGLOBREG_CONFIG);
WriteHWReg ( pvRegsBase,
MBX1_TAGLOBREG_CONFIG,
ps3D->ui32TAConfigRegVal | MBX1_TACONFIG_DEALLOC_GBL );
/*
Let's do the partial render
*/
for(i=0; i<psRenderCmd->ui32RegCount; i++)
{
switch(ps3DRegs[i].ui32RegAddr)
{
case MBX1_GLOBREG_RGNBASE :
WriteHWReg (pvRegsBase, MBX1_GLOBREG_RGNBASE, psCSInfo->RgnHeaderDevVAddr.uiAddr);
break;
default:
WriteHWReg (pvRegsBase, ps3DRegs[i].ui32RegAddr, ps3DRegs[i].ui32RegVal);
break;
}
}
/*
We need to set the ZLS control register to ZLOAD here, as if there is only a
single partial render (the normal case with a reasonably sized parameter buffer)
then it will not be set and the main scene render will appear incorrect
*/
psZLSCtrlReg->ui32RegVal |= MBX1_ZLOADSTORE_ZLOAD;
}
/*--------------------------------- end of file ------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -