📄 tautils.c
字号:
/******************************************************************************
<module>
* Name : tautils.c
* Title : D3DM primcopy routines
* Author(s) : Imagination Technologies
* Created : 18 March 2004
*
* Copyright : 2004 by Imagination Technologies Limited.
* All rights reserved. No part of this software, either
* material or conceptual may be copied or distributed,
* transmitted, transcribed, stored in a retrieval system
* or translated into any human or computer language in any
* form by any means, electronic, mechanical, manual or
* other-wise, or disclosed to third parties without the
* express written permission of Imagination Technologies
* Limited, Unit 8, HomePark Industrial Estate,
* King's Langley, Hertfordshire, WD4 8LZ, U.K.
*
* Description : DrawPrimitive Entry Point for processing D3DMobile DP Commands,
* and DP Operation Handlers
*
* Platform : Windows CE
*
</module>
$Log: tautils.c $
********************************************************************************/
#include "context.h"
/*****************************************************************************
FUNCTION : CalcTARegionClip
PURPOSE : Forms an appropriate TA region-clip control word to clip-to
a given pixel-area
PARAMETERS : psContext - Current 3D rendering context
psRect - The pixel-area to clip to
RETURNS : TA region clip control word.
*****************************************************************************/
DWORD CalcTARegionClip(LPD3DM_CONTEXT psContext, LPD3DMRECT psRect)
{
DEVICE3D *ps3DDevice;
DWORD dwRegionClip;
DWORD dwLeft, dwRight, dwTop, dwBottom;
DWORD dwX1, dwX2, dwY1, dwY2;
ps3DDevice = &GetDevInfo(psContext)->sDeviceSpecific.s3D;
dwX1 = psRect->x1;
dwX2 = psRect->x2;
dwY1 = psRect->y1;
dwY2 = psRect->y2;
/* Double size if Antialiasing enabled (covers 4x regions) */
if(psContext->dwFlags & D3DM_CONTEXT_SWFLAGS_SUPERSAMPLEX)
{
dwX1 *= 2;
dwX2 *= 2;
}
if(psContext->dwFlags & D3DM_CONTEXT_SWFLAGS_SUPERSAMPLEY)
{
dwY1 *= 2;
dwY2 *= 2;
}
/*
Round down TA region clip rect (top and left) to nearest tile
granularity boundaries outside viewport rectangle.
*/
RoundToTileGranBoundary(psContext, FALSE, dwX1, dwY1, NULL, NULL, &dwLeft, &dwTop);
/*
Round up TA region clip rect (right and bottom) to nearest tile
granularity boundaries outside viewport rectangle.
*/
RoundToTileGranBoundary(psContext, TRUE, dwX2, dwY2, NULL, NULL, &dwRight, &dwBottom);
/*
Region clip isn't specified in tiles, rather 16 pixel units.
For MBX this is our pseudo tile size, got from the product
of tile size and tile granularity
*/
dwLeft /= ps3DDevice->ui32TileXGran;
dwRight /= ps3DDevice->ui32TileXGran;
dwTop /= ps3DDevice->ui32TileYGran;
dwBottom /= ps3DDevice->ui32TileYGran;
/*
Setup region-clip word to clip everything outside the calculated
tile-region
*/
dwRegionClip = MBX1_TASTATERGNCLIP_CLIPOUTSIDE;
dwRegionClip |= (dwLeft << MBX1_TASTATERGNCLIP_LEFTCLIPSHIFT) &
(~MBX1_TASTATERGNCLIP_LEFTCLIPCLRMASK);
dwRegionClip |= (dwRight << MBX1_TASTATERGNCLIP_RIGHTCLIPSHIFT) &
(~MBX1_TASTATERGNCLIP_RIGHTCLIPCLRMASK);
dwRegionClip |= (dwTop << MBX1_TASTATERGNCLIP_TOPCLIPSHIFT) &
(~MBX1_TASTATERGNCLIP_TOPCLIPCLRMASK);
dwRegionClip |= (dwBottom << MBX1_TASTATERGNCLIP_BOTTOMCLIPSHIFT) &
(~MBX1_TASTATERGNCLIP_BOTTOMCLIPCLRMASK);
return dwRegionClip;
}
/*****************************************************************************
FUNCTION : UpdateTACtlAnd3DState
PURPOSE : Updates the TA/3D control state required for the next primitive,
and submits any changes to the HW.
PARAMETERS : psContext - Current 3D rendering context
RETURNS : void
*****************************************************************************/
void UpdateTACtlAnd3DState(LPD3DM_CONTEXT psContext)
{
PHWTACTL3DSTATE psHWTACtl3DState;
PHWSTATECTL psHWStateCtl;
PTRANSIENT_STATE psTState;
DWORD dwStateChanged;
DWORD i;
D3DM_DPF((DPF_ENTRY, "->UpdateTACtlAnd3DState"));
psTState = &psContext->sTState;
psHWTACtl3DState = &psContext->sHWState.sTACtl3DState;
psHWStateCtl = &psContext->sHWStateCtl;
dwStateChanged = psHWStateCtl->dwTACtl3DStateChanged;
D3DM_DPF((DPF_TA, "UpdateTACtlAnd3DState: Change flags 0x%8.8lX", dwStateChanged));
/*
Perform any final 'pre-primitive' processing of the HW-state for each
texture-stage, and determine the overall HW pass and layer counts
required
*/
for (i = 0; i < MBX1_MAXTEXTURE_LAYERS; i++)
{
PMBX1_TSPLAYER_STATE psTSPLState;
LPD3DM_SURFACE psSurfData;
/* Stop if this layer is not enabled */
if(!(psContext->dwFlags & (D3DM_CONTEXT_SWFLAGS_LAYER0ENABLED << i)))
{
break;
}
psTSPLState = &psHWTACtl3DState->sTSPLState[i];
psSurfData = psTState->sLState[i].psSurfData;
/* Add stride into parameters if texture hasn't been blitted to */
if(psSurfData)
{
if(!(psSurfData->dwFlags & D3DM_SURFACE_FLAGS_TWIDDLED))
{
DWORD dwStridePixel;
DWORD dwStride;
/*
Get Pixel stride from current top level map.
This should always be correc teven when mipmapping is disabled
*/
dwStridePixel = psSurfData->sDescription.sTexture.psMapDetails->psCurrentTopLevel->dwStridePixel;
/*
NB: MBX1 stride is in terms of 8-pixels
surface-data stride is in pixels
*/
dwStride = (DWORD)dwStridePixel >> 3;
/* Write stride into layer-words 1 and 2 */
psTSPLState->dwLCtl1 &= ~MBX1_TSPPL1_TEXSTRIDE_LSB;
psTSPLState->dwLCtl1 |= (dwStride << MBX1_TSPPL1_TEXSTRIDE_LSBSHIFT) &
MBX1_TSPPL1_TEXSTRIDE_LSB;
psTSPLState->dwLCtl2 &= MBX1_TSPPL2_TEXSTRIDECLRMASK;
psTSPLState->dwLCtl2 |= (dwStride << (MBX1_TSPPL2_TEXSTRIDESHIFT - 1)) &
(~MBX1_TSPPL2_TEXSTRIDECLRMASK);
/*
Flag that this layer has potentially changed
*/
dwStateChanged |= MBX1_TASTATEPRES_LAYER0CTL << i;
}
}
}
/* Submit the new state (only written if different to current state) */
TACSWriteTACtlAnd3DState(psContext,
dwStateChanged,
psHWTACtl3DState,
FALSE);
/*
Reset the TA-ctl/3D-state 'state-changed' flags (since all changed
state has now been output)
*/
psHWStateCtl->dwTACtl3DStateChanged = 0;
D3DM_DPF((DPF_EXIT, "<-UpdateTACtlAnd3DState"));
}
/*****************************************************************************
FUNCTION : TACSWriteTACtlAnd3DState
PURPOSE : Writes a TA-control and 3D-state block to the TA control stream
PARAMETERS : psContext - Current 3D rendering context
dwStateChanged - State presence flags indicating which
states are to be written (see
MBX1_TASTATEPRES_xxx flags)
psNewTACtl3DState - HW-state structure containing the new
TA-ctl/3D-state to write
bForceWrite - Control to force state to be written
even if it is the same as the current
state-data.
RETURNS : void
*****************************************************************************/
void TACSWriteTACtlAnd3DState(LPD3DM_CONTEXT psContext,
DWORD dwStateChanged,
PHWTACTL3DSTATE psNewTACtl3DState,
BOOL bForceWrite)
{
PHWSTATECTL psHWStateCtl;
DWORD pdwBlockData[(sizeof(HWTACTL3DSTATE)/sizeof(DWORD)) + 1];
PDWORD pdwDest;
PDWORD pdwCurrState;
PDWORD pdwNewState;
DWORD dwStateSetup;
DWORD dwStateLeft;
DWORD dwStateToWrite;
DWORD dwState;
DWORD i;
static DWORD pdwStateSizes[] =
{
1, /* ISP/TSP state = 1 DWORD */
1, /* TSP per-object state = 1 DWORD */
3, /* TSP layer 0 state = 3 DWORDs */
3, /* TSP layer 1 state = 3 DWORDs */
1, /* TA region-clip = 1 DWORD */
1, /* VGP input-format = 1 DWORD */
1, /* TA fixed-point format = 1 DWORD */
6, /* VGP viewport transform = 6 DWORDs */
1, /* VGP W-clamp value = 1 DWORD */
};
#if defined(DEBUG) || defined(D3DM_RETAIL_DBGOUT)
static PSTR ppszStateName[] =
{
"ISP/TSP word",
"TSP word",
"TSP Layer 0 state",
"TSP Layer 1 state",
"TA region clip word",
"VGP input-def word",
"TA input-format word",
"viewport transform",
"W-clamp value"
};
#endif /*#if defined(DEBUG) || defined(D3DM_RETAIL_DBGOUT)*/
D3DM_DPF((DPF_ENTRY, "->TACSWriteTACtlAnd3DState"));
#if !defined(SUPPORT_VGP) && !defined (SUPPORT_VGP_LITE)
/*
Mask out VGP-related states.
*/
dwStateChanged &= ~ (MBX1_TASTATEPRES_VGP_IFDEFINITION |
MBX1_TASTATEPRES_VGP_VIEWPORTTRANS |
MBX1_TASTATEPRES_VGP_WCLAMPVAL);
#endif /* #if !defined(SUPPORT_VGP) */
/* Do nothing if no state needs changing */
dwStateChanged &= ~MBX1_TASTATEPRES_CLRMASK;
if(!dwStateChanged)
{
D3DM_DPF((DPF_TA,"TACSWriteTACtlAnd3DState: No new-state flags set. Doing nothing!"));
return;
}
D3DM_DPF((DPF_TA, "TACSWriteTACtlAnd3DState: New-state flags 0x%8.8lX", dwStateChanged));
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->dwTACtl3DStateSetup & (~MBX1_TASTATEPRES_CLRMASK);
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;
}
/*
Setup where we will be copying the state from and to
NB: Leave the first DWORD in the block-data free for the header
*/
pdwCurrState = (PDWORD)&psContext->sCurrHWState.sTACtl3DState;
pdwNewState = (PDWORD)psNewTACtl3DState;
pdwDest = &pdwBlockData[1];
/*
Check each state in turn to see if we need to write it, stopping once
all the changed state has been considered.
*/
dwState = MBX1_TASTATEPRES_ISPCTL;
i = 0;
while(dwStateLeft)
{
DWORD dwStateSize;
dwStateSize = pdwStateSizes[i];
/* Has this state changed? */
if(dwStateLeft & dwState)
{
BOOL bCopyState;
/*
Offset the state read/write pointers so that the switch-based
compare/copy code works.
*/
pdwNewState -= 6 - dwStateSize;
pdwCurrState -= 6 - dwStateSize;
/*
Do we need to copy the new state? Copy if it has not been
written before, or it is different from the current state.
*/
bCopyState = TRUE;
if(dwStateSetup & dwState)
{
/*
Compare current and new state
*/
switch(dwStateSize)
{
case 6: if (pdwNewState[0] ^ pdwCurrState[0]) break;
case 5: if (pdwNewState[1] ^ pdwCurrState[1]) break;
case 4: if (pdwNewState[2] ^ pdwCurrState[2]) break;
case 3: if (pdwNewState[3] ^ pdwCurrState[3]) break;
case 2: if (pdwNewState[4] ^ pdwCurrState[4]) break;
case 1: if (pdwNewState[5] ^ pdwCurrState[5]) break;
default: bCopyState = FALSE;
}
}
if(bCopyState)
{
D3DM_DPF((DPF_TA, "TACSWriteTACtlAnd3DState: Need to send %hs. Adding to state-block", ppszStateName[i]));
/*
Copy the new state into the state block to write, and into
the current state data.
*/
pdwDest -= 6 - dwStateSize;
switch (dwStateSize)
{
case 6: pdwCurrState[0] = pdwDest[0] = pdwNewState[0];
case 5: pdwCurrState[1] = pdwDest[1] = pdwNewState[1];
case 4: pdwCurrState[2] = pdwDest[2] = pdwNewState[2];
case 3: pdwCurrState[3] = pdwDest[3] = pdwNewState[3];
case 2: pdwCurrState[4] = pdwDest[4] = pdwNewState[4];
case 1: pdwCurrState[5] = pdwDest[5] = pdwNewState[5];
}
pdwDest += 6;
}
else
{
D3DM_DPF((DPF_TA, "TACSWriteTACtlAnd3DState: %hs unchanged, not adding in state-block", ppszStateName[i]));
/*
State not copied. Removed from the state we have to
write at the end.
*/
dwStateToWrite ^= dwState;
}
/*
Move to the data for the next state (note the offset to
these pointers above)
*/
pdwNewState += 6;
pdwCurrState += 6;
/* Remove this state from the ones we have to deal with */
dwStateLeft ^= dwState;
}
else
{
/*
State not changed. Skip the data for this state
*/
pdwNewState += dwStateSize;
pdwCurrState += dwStateSize;
}
/* Move onto next state to test */
dwState <<= 1;
i++;
}
/* If we have some state to write, do so */
if(dwStateToWrite)
{
DWORD dwBlockSize;
D3DM_DPF((DPF_TA, "TACSWriteTACtlAnd3DState: Writing block with flags 0x%8.8lX", dwStateToWrite));
/* Add header to start of block */
pdwBlockData[0] = MBX1_TAOBJTYPE_STATE | dwStateToWrite;
/* Output the block */
DBG_DECODETACTL3DSTATEBLOCK(psContext, pdwBlockData);
dwBlockSize = (pdwDest - pdwBlockData) * sizeof(DWORD);
TACSWriteData(psContext, pdwBlockData, dwBlockSize);
}
/* Record which state we have just written out */
psHWStateCtl->dwTACtl3DStateSetup |= dwStateToWrite;
D3DM_DPF((DPF_EXIT, "<-TACSWriteTACtlAnd3DState"));
}
/*********************************************************************************
VGP Specific
*********************************************************************************/
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
/*****************************************************************************
FUNCTION : UpdateVGPControlState
PURPOSE : Updates the VGP-control state required for the next primitive,
and submits any changes to the HW.
PARAMETERS : psContext - Current 3D rendering context
RETURNS : void
*****************************************************************************/
void UpdateVGPControlState(LPD3DM_CONTEXT psContext)
{
PHWVGPCONTROL psNewVGPControlState;
PHWSTATECTL psHWStateCtl;
DWORD dwStateChanged;
D3DM_DPF((DPF_ENTRY, "->UpdateVGPControlState"));
psHWStateCtl = &psContext->sHWStateCtl;
dwStateChanged = psHWStateCtl->dwVGPCtlStateChanged;
/* Quit if nothing's changed */
if(!dwStateChanged)
{
D3DM_DPF((DPF_TA,"UpdateVGPControlState: no update required (no state changed)"));
return;
}
D3DM_DPF((DPF_TA,"UpdateVGPControlState: Change flags 0x%8.8lX", dwStateChanged));
/*
Submit the new VGP-control state (only written if different to
current state)
*/
psNewVGPControlState = &psContext->sHWState.sVGPControl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -