📄 mbx.c
字号:
We must round to the appropriate number of tiles
and (if req'd) to nearest MT:
MBX - nearest Macrotile
MBXLite - nearest even tile
*/
eError = CalcTileDimensions(psDevInfo,
ps3DCtl,
ui32Width,
ui32Height);
if(eError == PVRSRV_OK)
{
eError = Setup3DCtl(psDevInfo, psParamBuff, ps3DCtl, ui32AAFlags);
if (eError == PVRSRV_OK)
{
/* Generate Unique ID from kernel address of structure */
ps3DCtl->sSharedData.ui32UniqueID = (IMG_UINT32)ps3DCtl;
/* Add to linked list of TARender infos. */
ps3DCtl->psNext = psParamBuff->ps3DCtlList;
psParamBuff->ps3DCtlList = ps3DCtl;
(*ppsTARenderInfo)->psSharedData = &ps3DCtl->sSharedData;
/* and setup tailptrs for user */
(*ppsTARenderInfo)->pvTailPtrs = ps3DCtl->sSharedData.pvTailPtrsKM;
/* Require resource manager to track resource */
ps3DCtl->psResItem = ResManRegisterRes(( PRESMAN_ITEM)IMG_NULL,
RESMAN_TYPE_RENDERTARGET,
psDevInfo,
(IMG_UINT32)*ppsTARenderInfo,
RemoveRenderTargetCallBack,
RESMAN_AUTOFREE_LEV1);
if (ps3DCtl->psResItem == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVAddRenderTarget: Failed to register resource"));
eError = PVRSRV_ERROR_GENERIC;
}
}
}
}
return(eError);
}
/*!
******************************************************************************
@Function PVRSRVRemoveRenderTarget
@Description
Removes a render target from the parameter buffer. Frees region headers and tail
pointers.
@Input psDevData :
@Input psInfo:
@Return PVRSRV_ERROR :
******************************************************************************/
IMG_EXPORT PVRSRV_ERROR PVRSRVRemoveRenderTarget (PVRSRV_DEV_DATA *psDevData, PVRSRV_TARENDERINFO *psInfo)
{
PVRSRV_ERROR eError;
PVR3DIF_3DCTL *ps3DCtl;
ps3DCtl = (PVR3DIF_3DCTL *)psInfo->psSharedData;
if(ps3DCtl->psResItem)
{
eError = ResManFreeResByPtr(ps3DCtl->psResItem);
}
else
{
/* Resource not managed call the free callback directly */
eError = RemoveRenderTargetCallBack(0,(IMG_PVOID)psDevData->psDevInfoKM, (IMG_UINT32)psInfo);
}
return(eError);
}
/*!
******************************************************************************
@Function SetupHWRegs
@Description
Setup registers for event manager
@Input psDevInfo - devinfo
@Input ui32Offset - Offset from start of PB that EVM will manage
@Return none
******************************************************************************/
static IMG_VOID SetupHWRegs(PVRSRV_DEV_INFO *psDevInfo, IMG_UINT32 ui32Offset)
{
PVR3DIF_PARAMBUFFER *psParamBuffer = (PVR3DIF_PARAMBUFFER *)psDevInfo->sDeviceSpecific.s3D.hParamBuffer;
IMG_PVOID pvRegsBase = psDevInfo->sDevLocation.pvRegsBaseKM;
PVRSRV_HWREG *psRegs;
IMG_UINT32 ui32ParamBase;
IMG_UINT32 ui32NumBlocks;
IMG_UINT32 ui32PageTableBase;
IMG_UINT32 ui32StartPage;
IMG_UINT32 ui32EndPage;
volatile IMG_UINT32 ui32IntStatus;
IMG_UINT32 ui32Orig;
IMG_UINT32 i;
#ifdef SUPPORT_KYRO_AS_MBX_DEVICE
/*
Avoid "unreferenced local variable" warning.
*/
ui32IntStatus = 0;
#endif
ui32ParamBase = psParamBuffer->ParamDevVAddr.uiAddr;
ui32NumBlocks = psParamBuffer->ui32NumBlocks;
/*
Calculate the required start-page, end-page, and pagetable address (an offset
into FB)
*/
ui32PageTableBase = psParamBuffer->PageTableDevVAddr.uiAddr;
ui32StartPage = (ui32ParamBase + ui32Offset) / MBX1_TA_EVM_PAGETBL_GRAN;
ui32EndPage = ui32StartPage + ui32NumBlocks - 1;
/*
Setup parameter management regs
*/
psRegs = psParamBuffer->asHWRegs;
i = 0;
psRegs[i].ui32RegAddr = MBX1_TAGLOBREG_EVM_PAGETBL_BASE;
psRegs[i++].ui32RegVal = ui32PageTableBase;
psRegs[i].ui32RegAddr = MBX1_TAGLOBREG_EVM_LIST_START;
psRegs[i++].ui32RegVal = ui32StartPage;
psRegs[i].ui32RegAddr = MBX1_TAGLOBREG_EVM_LIST_END;
psRegs[i++].ui32RegVal = ui32EndPage;
psRegs[i].ui32RegAddr = MBX1_TAGLOBREG_EVM_INIT;
psRegs[i++].ui32RegVal = 1;
psRegs[i].ui32RegAddr = MBX1_TAGLOBREG_OBJDATABASE;
psRegs[i++].ui32RegVal = ui32ParamBase;
psRegs[i].ui32RegAddr = MBX1_GLOBREG_3D_ZL_BACKGROUND_TAG;
psRegs[i++].ui32RegVal = MBX1_3DZLBG_TAG_OBJ_TEXTURED |
(8 << MBX1_3DZLBG_TAG_OBJ_MASK_SHIFT) | /* 8 is a Magic number from the programming guide */
0; /* 0 offset from Object base address - BGObj is at bottom of PB */
/* save reg count */
psParamBuffer->ui32HWRegCount = i;
PVR_DPF((PVR_DBG_ERROR,"ui32PageTableBase = %x",ui32PageTableBase));
PVR_DPF((PVR_DBG_ERROR,"ui32StartPage = %x",ui32StartPage));
PVR_DPF((PVR_DBG_ERROR,"ui32EndPage = %x",ui32EndPage));
PVR_DPF((PVR_DBG_ERROR,"ui32ParamBase = %x",ui32ParamBase));
/*
Initialise the EVM free-page list
0) Enable 3D core
1) Disable EVM_DALLOC interrupt
2) Write the required start, end and base address for the page-list
3) Write to EVM_INIT
4) Wait for EVM_DALLOC bit in the interrupt status word
5) Reset the EVM_DALLOC interrupt
6) Re-enable EVM_DALLOC interrupts
7) Disable 3D core
*/
SysClearDeviceInterrupts(psDevInfo, pvRegsBase, MBX1_INT_EVM_DALLOC);
PDUMPREG (IMG_NULL, PDUMPTAGS_REG_MBX, MBX1_GLOBREG_INT_CLEAR, MBX1_INT_EVM_DALLOC);
/* Disable EVM_DALLOC interrupts */
ui32Orig = SysDisableDeviceInterrupts(psDevInfo, pvRegsBase, MBX1_INT_EVM_DALLOC);
/* write regs */
WriteHWRegs(pvRegsBase, psParamBuffer->ui32HWRegCount, psRegs);
PDUMPREGARRAY (IMG_NULL, PDUMPTAGS_REG_MBX, psRegs, psParamBuffer->ui32HWRegCount);
#ifdef SUPPORT_KYRO_AS_MBX_DEVICE
/* inform the 3dsim EVM init has started */
REGWRITE3DSIM(MBX1_TAGLOBREG_EVM_INIT,1);
#endif
/* Wait for EVM_DALLOC bit in the interrupt status word */
do
{
ui32IntStatus = SysDecodeDeviceInterrupts(psDevInfo, pvRegsBase);
} while ((ui32IntStatus & MBX1_INT_EVM_DALLOC) == 0);
/* Reset the EVM_DALLOC interrupt */
SysClearDeviceInterrupts(psDevInfo, pvRegsBase, MBX1_INT_EVM_DALLOC);
PDUMPREG (IMG_NULL, PDUMPTAGS_REG_MBX, MBX1_GLOBREG_INT_CLEAR, MBX1_INT_EVM_DALLOC);
#ifdef SUPPORT_KYRO_AS_MBX_DEVICE
/* inform the 3dsim Int's have been cleared */
REGWRITE3DSIM(MBX1_GLOBREG_INT_CLEAR,MBX1_INT_EVM_DALLOC);
#endif
/* Re-enable EVM_DALLOC interrupts */
SysEnableDeviceInterrupts(psDevInfo, pvRegsBase, ui32Orig);
}
/*!
******************************************************************************
@Function BitInterleaveBA
@Description
Performs a bitwise Interleave of two 16-bit values A and B to
form a 32-bit result, with the LSB of A forming the LSB of
the result.
@Input wA - 16-bit word to merge
@Input wB - 16-bit word to merge
@Return result
******************************************************************************/
IMG_UINT32 BitInterleaveBA(IMG_UINT16 ui16Val1, IMG_UINT16 ui16Val2)
{
IMG_UINT32 ui32Result;
IMG_UINT32 ui32A, ui32B;
IMG_UINT32 j;
IMG_UINT32 i;
ui32Result = 0;
ui32A = (IMG_UINT32)ui16Val1;
ui32B = (IMG_UINT32)ui16Val2;
for (i = 0x1, j = 0; i < 0x10000; i <<= 1)
{
ui32Result |= (ui32A & i) << j;
j++;
ui32Result |= (ui32B & i) << j;
}
return ui32Result;
}
/*!
******************************************************************************
@Function CalcMacrotileTileSize
@Description
Calculates the appropriate macrotile dimension (in tiles)
from a screen dimension (in tiles)
@Input number of tiles in given dimension
@Return number of tiles in given MT dimension
******************************************************************************/
static IMG_UINT32 CalcMacrotileTileSize(IMG_UINT32 ui32TileSize)
{
IMG_UINT32 ui32MTTileSize;
/*
Pixels:
-------
Screen Size Macrotile Size
<= 512 64
<= 1024 128
<= 2048 256
Tiles:
-------
Screen Size Macrotile Size
<= 512 64
<= 1024 128
<= 2048 256
*/
if (ui32TileSize <= MBX_MT_TILE_THRESHOLD_0)
{
ui32MTTileSize = MBX_MT_TILE_SIZE_0;
}
else if (ui32TileSize <= MBX_MT_TILE_THRESHOLD_1)
{
ui32MTTileSize = MBX_MT_TILE_SIZE_1;
}
else if (ui32TileSize <= MBX_MT_TILE_THRESHOLD_2)
{
ui32MTTileSize = MBX_MT_TILE_SIZE_2;
}
else
{
PVR_DPF((PVR_DBG_ERROR,"CalcMacrotileTileSize: render target size too big"));
ui32MTTileSize = 0;
}
return ui32MTTileSize;
}
/*!
******************************************************************************
@Function Setup3DCtl
@Description
sets up 3d PB details
@Input psDevInfo
@Input psParamBuff
@Input ps3DCtl
@Input ui32AAFlags
@Return PVRSRV_ERROR
******************************************************************************/
static PVRSRV_ERROR Setup3DCtl( PVRSRV_DEV_INFO *psDevInfo,
PVR3DIF_PARAMBUFFER *psParamBuff,
PVR3DIF_3DCTL *ps3DCtl,
IMG_UINT32 ui32AAFlags)
{
IMG_UINT32 ui32TotalRegions;
IMG_UINT32 ui32TotalTails;
IMG_UINT32 ui32TotalTails1;
IMG_UINT32 ui32TotalTails2;
IMG_UINT32 ui32NumTilesX;
IMG_UINT32 ui32NumTilesY;
IMG_UINT32 ui32TailSize;
IMG_VOID *pvTailsLin;
IMG_VOID *pvContextLin;
IMG_DEV_VIRTADDR TailPointerDevVAddr;
IMG_DEV_VIRTADDR ContextDevVAddr;
PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
IMG_UINT32 i, ui32AllocSize;
/*
Tile dimensions, as calc'ed by CalcTileDimensions
*/
ui32NumTilesX = ps3DCtl->sSharedData.ui32MTilesX * ps3DCtl->sSharedData.ui32XTilesPerMT;
ui32NumTilesY = ps3DCtl->sSharedData.ui32MTilesY * ps3DCtl->sSharedData.ui32YTilesPerMT;
/*
* Allocate Complex Scene Information structs per MT
*/
ui32AllocSize = ps3DCtl->sSharedData.ui32MTilesX * ps3DCtl->sSharedData.ui32MTilesY * sizeof(PVR_CS_INFO);
if(HostAllocMem( PVRSRV_HOST_NON_PAGEABLE_HEAP,
ui32AllocSize,
(IMG_VOID **)&ps3DCtl->psCSInfoMemKM, 0) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"Unable to allocate psCSInfoMemKM"));
goto ErrorExit;
}
HostMemSet((IMG_VOID *)ps3DCtl->psCSInfoMemKM, 0, ui32AllocSize);
/*
Allocate tail-pointer space required
NB: Tail-pointer addressing is twiddled on MBX - the tail
pointer address is generated by interleaving the bits from
a tile's X and Y tile-position (LSB = X-LSB). The largest
possible tail-pointer address if therefore the bit-interleaved
X and Y render-target tile dimensions.
Additionally, the tail pointer data is accessed in blocks of
8 DWORDs, so we must round-up the overall space to a multiple
of this, to avoid the TA writing off the end of our tail-
pointer data.
*/
ui32TotalTails1 = BitInterleaveBA((IMG_UINT16)ui32NumTilesX, (IMG_UINT16)ui32NumTilesY);
ui32TotalTails2 = BitInterleaveBA((IMG_UINT16)ui32NumTilesY, (IMG_UINT16)ui32NumTilesX);
if (ui32TotalTails1 > ui32TotalTails2)
{
ui32TotalTails = ui32TotalTails1;
}
else
{
ui32TotalTails = ui32TotalTails2;
}
/*
Calculate the space to allocate - each tail-pointer is 1 IMG_UINT32,
and we must round the size up to a multiple of 8 DWORDs.
NB: Only 1 set of tail-pointer data is required, as the data
is only used by the TA (i.e. no simultaneous TA and 3D-core
access)
*/
ui32TailSize = ui32TotalTails * sizeof(IMG_UINT32);
ui32TailSize += 8*sizeof(IMG_UINT32) - 1;
ui32TailSize &= ~(8*sizeof(IMG_UINT32) - 1);
/*
Allocate memory for tail-pointers
NB: Only 1 set of tail-pointer data is required, as the data
is only used by the TA (i.e. no simultaneous TA and 3D-core
access)
*/
eError = AllocStaticFBMem( psDevInfo,
0,
ui32TailSize,
MBX1_ADDRGRAN_TAILPTR,
&pvTailsLin,
&TailPointerDevVAddr);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"ERROR - Failed to alloc FB mem for TA/Render size related data !"));
goto ErrorExit;
}
/* and be sure to initialise them */
HostMemSet(pvTailsLin, 0, ui32TailSize);
ps3DCtl->sSharedData.pvTailPtrsKM = pvTailsLin;
ps3DCtl->sSharedData.TailPtrDevVAddr = TailPointerDevVAddr;
ps3DCtl->sSharedData.ui32TailPtrSize = ui32TailSize;
/*
Allocate region-header space required
*/
ui32TotalRegions = ui32NumTilesX * ui32NumTilesY;
#if defined(FIX_HW_PRN_223) || defined(FIX_HW_PRN_251)
/* n.b. extra RH req'd to fix CS HW bug */
ui32TotalRegions++;
#endif
/*
calculate what we can for the background object (U and V)
*/
CalcHWBGO3DCtl(&psDevInfo->sDeviceSpecific.s3D, ps3DCtl, ui32AAFlags);
/*
Allocate space to save and restore the TA and EVM context data
We save data per macrotile with a maximum of 65 MTs inc. the global list
TA saves 1 IMG_UINT32/MT -> 260bytes
EVM saves 2 IMG_UINT32/MT -> 520bytes
*/
eError = AllocStaticFBMem( psDevInfo,
0,
MBX1_TACONTEXT_SIZE,
MBX1_ADDRGRAN_TACONTEXT,
&pvConte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -