📄 clear.c
字号:
/******************************************************************************
<module>
* Name : clear.c
* Title : D3DM Clear routines
* Author(s) : Imagination Technologies
* Created : 2 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 : D3DM Clear routines
*
* Platform : Windows CE
*
</module>
********************************************************************************/
#include "context.h"
/*****************************************************************************
Structures
*****************************************************************************/
typedef struct _TEXTUREDRECT_
{
LPD3DM_CONTEXT psContext;
D3DMRECT sSrcRect;
D3DMRECT sDestRect;
DWORD dwFillDepth;
DWORD dwFillRHW;
float fUScale;
float fVScale;
BOOL bFullScreenClip;
}
TEXTUREDRECT, *PTEXTUREDRECT;
/*****************************************************************************
############################### CLEARS:#######################################
*****************************************************************************/
/*****************************************************************************
FUNCTION : ClearRectangle
PURPOSE : Used to render a rectangle for supporting Clear2.
PARAMETERS : psContext - A 3D rendering context
psRect - The position and size of the required clear-
object (ignored if bFullscreen is TRUE)
dwFillColour - The base (diffuse) colour to use for the clear-
object
dwFillDepth - The depth (Z) value to use for the clear-object
dwFillRHW - The RHW value to use for the clear objecr
bFullScreen - TRUE if the object should be created to cover
the entire current render-target surface
RETURNS : None.
*****************************************************************************/
void ClearRectangle(LPD3DM_CONTEXT psContext,
LPD3DMRECT psRect,
DWORD dwFillColour,
DWORD dwFillDepth,
DWORD dwFillRHW,
BOOL bFullScreen)
{
PHWSTATE psHWState;
PHWSTATECTL psHWStateCtl;
LPD3DM_SURFACE psRenderTarget;
DWORD adwVertex[20], *pdwVertex;
DWORD dwTAPrimCtl;
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
DWORD dwVGPClipCtl;
DWORD dwFVFCode;
DWORD dwTnLFlags;
VSIFDEF sVSIFDef;
#endif
DWORD dwWidth, dwHeight;
NTV_TYPE ntvX1, ntvX2, ntvY1, ntvY2;
DEVICE3D *p3DDevice;
PVR3DIF_SHAREDDATA *p3DSharedData;
p3DDevice = &(GetDevInfo(psContext)->sDeviceSpecific.s3D);
psHWState = &psContext->sHWState;
psHWStateCtl = &psContext->sHWStateCtl;
psRenderTarget = psContext->psCurrentRenderTarget;
p3DSharedData = psRenderTarget->sDescription.sSurface.psTARenderInfo->psSharedData;
/*
Setup appropriate primitive block-header controls
*/
dwTAPrimCtl = MBX1_TAPRIM_NONPERSPCORRECT |
MBX1_TAPRIM_ZBIAS_MODEINCREASING |
(0 << MBX1_TAPRIM_ZBIAS_SHIFT) |
MBX1_TAPRIM_CULLMODENONE |
(psContext->dwTAPrimCtl & MBX1_TAPRIM_WBUFFERING_ENABLE);
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
/* Set up the FVF code and TnL flags for pass through shader */
dwFVFCode = D3DMFVF_XYZRHW_FLOAT |
D3DMFVF_DIFFUSE;
dwTnLFlags = PVRD3DTNL_FLAGS_DIFFUSE_PRESENT;
/*
Configure the FVF passthough-shader for the FVF we require
*/
VSIFDefSetupForFVF(psContext, &sVSIFDef, dwFVFCode, 5<<2);
/* set up the pass-through vertex-shader for this clear data type */
VGPTNLSetUpPassThroughShader(psContext, dwTnLFlags);
/* Ensure our VGP instructions are up to date before sending anything */
UpdateVGPInstructions(psContext);
/* Update the vertex-copy data */
SetupVertexCopyData(psContext, &sVSIFDef);
/* update Interface Def HW State */
psContext->sHWState.sTACtl3DState.dwVGPIFDef = sVSIFDef.dwVGPIFDef;
psContext->sHWStateCtl.dwTACtl3DStateChanged |= MBX1_TASTATEPRES_VGP_IFDEFINITION;
/*
Write out all the HW-state that has just changed as a result of
loading the passthrough shader
*/
TACSWriteTACtlAnd3DState(psContext,
MBX1_TASTATEPRES_VGP_IFDEFINITION,
&psHWState->sTACtl3DState,
FALSE);
TACSWriteVGPControlState(psContext,
psHWStateCtl->dwVGPCtlStateChanged,
&psHWState->sVGPControl,
FALSE);
/*
Reset the VGP-control 'state-changed' flags (since all changed
state has now been output)
*/
psHWStateCtl->dwVGPCtlStateChanged = 0;
/*
Disable stuff in the VGP-clip control word that isn't required in
this case (since we are suppying already transformed (i.e. in
screen-space) vertices.
*/
dwVGPClipCtl = psContext->dwVGPClipCtl;
dwVGPClipCtl &= ~(MBX1_VGPCLIPCTL_CLIPPLANES_MASK |
MBX1_VGPCLIPCTL_VIEWPORTTRANS_ENABLE |
MBX1_VGPCLIPCTL_STARTSECTION_MASK);
#endif
/*
Calculate width and height rounded up to next tile boundary.
MACROTILE * TILESPERMACROTILE * PIXELSINTTILE
- FIXME:MAY BREAK IN ANTI-ALIAS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
dwWidth = p3DSharedData->ui32XTilesPerMT *
p3DSharedData->ui32MTilesX *
p3DDevice->ui32PixelsInTileX;
dwHeight = p3DSharedData->ui32YTilesPerMT *
p3DSharedData->ui32MTilesY *
p3DDevice->ui32PixelsInTileY;
/*
Begin a new vertex-strip
*/
TACSWritePrimHdr(psContext, dwTAPrimCtl, MBX1_TAOBJTYPE_VERTEXFACESTRIP);
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
TACSWriteVGPClipWord(psContext, dwVGPClipCtl);
#endif
ntvX1 = LONG_AS_NTV(psRect->x1);
ntvY1 = LONG_AS_NTV(psRect->y1);
/*
Are we fullscreen?
*/
if (bFullScreen)
{
/*
If dest rectangle is full-rendersurface,
send single triangle scaled up in size to cover
full screen.
*/
D3DM_DPF((DPF_MESSAGE, "full render srf clear - sending single tri"));
ntvX2 = Add(ntvX1, LONG_AS_NTV(2 * dwWidth));
ntvY2 = Add(ntvY1, LONG_AS_NTV(2 * dwHeight));
}
else
{
/*
If dest rectangle is smaller than full-rendersurface,
send two-triangle quad as normal.
*/
D3DM_DPF((DPF_MESSAGE, "not full render srf clear - sending 2-tri quad"));
ntvX2 = LONG_AS_NTV(psRect->x2);
ntvY2 = LONG_AS_NTV(psRect->y2);
/*
Increase full-surface blits to next tilesize up.
*/
if (psRect->x2 == (int) psRenderTarget->dwWidth)
{
ntvX2 = LONG_AS_NTV(dwWidth);
}
if (psRect->y2 == (int) psRenderTarget->dwHeight)
{
ntvY2 = LONG_AS_NTV(dwHeight);
}
}
/*
init scratch ptr
*/
pdwVertex = adwVertex;
/*
Setup vertex data for 2 triangles using 4 vertices.
*/
*pdwVertex++ = TO_ULONG(ntvX1);
*pdwVertex++ = TO_ULONG(ntvY2);
*pdwVertex++ = dwFillDepth;
*pdwVertex++ = dwFillRHW;
*pdwVertex++ = dwFillColour;
*pdwVertex++ = TO_ULONG(ntvX1);
*pdwVertex++ = TO_ULONG(ntvY1);
*pdwVertex++ = dwFillDepth;
*pdwVertex++ = dwFillRHW;
*pdwVertex++ = dwFillColour;
if (!bFullScreen)
{
*pdwVertex++ = TO_ULONG(ntvX2);
*pdwVertex++ = TO_ULONG(ntvY2);
*pdwVertex++ = dwFillDepth;
*pdwVertex++ = dwFillRHW;
*pdwVertex++ = dwFillColour;
}
*pdwVertex++ = TO_ULONG(ntvX2);
*pdwVertex++ = TO_ULONG(ntvY1);
*pdwVertex++ = dwFillDepth;
*pdwVertex++ = dwFillRHW;
*pdwVertex++ = dwFillColour;
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
CopySelect(psContext,
(IMG_UINT8 *)adwVertex,
bFullScreen ? 4 : 3,
&sVSIFDef);
#else
TACSWriteData(psContext, (PVOID)adwVertex, (pdwVertex-adwVertex)<<2);
#endif
TACSWriteLastPrim(psContext);
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
/* update Interface Def HW State */
if(psContext->psVertexSource)
{
psContext->sHWState.sTACtl3DState.dwVGPIFDef = psContext->psVertexSource->sVSIFDef.dwVGPIFDef;
psContext->sHWStateCtl.dwTACtl3DStateChanged |= MBX1_TASTATEPRES_VGP_IFDEFINITION;
}
#endif /* #if defined(SUPPORT_VGP) */
}
/*****************************************************************************
FUNCTION : SendClear
PURPOSE : Handles clears for the draw-prim2 op.
PARAMETERS : psContext - D3D context
dwFlags - The type of clear to perform
dwFillColour - The colour to use when clearing the target
fFillDepth - The depth to use when clearing the depth-buffer
dwNumRects - The number of rects at lpRects
psRects - An array of dwNumRects rectangles
bFullScreen - Whether it is fullscreen or not
RETURNS : void
*****************************************************************************/
void SendClear( LPD3DM_CONTEXT psContext,
DWORD dwFlags,
DWORD dwFillColour,
float fFillDepth,
DWORD dwNumRects,
LPD3DMRECT psRects,
DWORD dwFSFlags)
{
LPD3DMRECT psRect;
HWTACTL3DSTATE sTACtl3DState;
DWORD dwStateChanged = 0;
DWORD dwDepth;
DWORD dwRHW;
DWORD i;
NTV_TYPE ntvD3DM_One = D3DM_One, ntvFillDepth;
D3DM_DPF((DPF_MESSAGE, "SendClear: flags %#8.8lX",dwFlags));
/*
Check if we have someting to do
*/
if((!dwNumRects) || (!(dwFlags & (D3DMCLEAR_ZBUFFER | D3DMCLEAR_TARGET))))
{
return;
}
PDUMPSTRING(psContext->psPDContext, "--Clear Object");
/*
Get the rectangle.
*/
psRect = psRects;
#if defined(FIX_HW_PRN_145)
/*
Setup TA-Ctl/3D state as required.
*/
sTACtl3DState.dwISPTSPCtl = MBX1_ISPTSPCTL_SRCBLENDONE |
MBX1_ISPTSPCTL_DESTBLENDZERO |
MBX1_ISPTSPCTL_BLENDOPMODEFOGNONE |
MBX1_ISPTSPCTL_CKDISABLE |
(0 << MBX1_ISPTSPCTL_NUMPASSESSHIFT)|
(0 << MBX1_ISPTSPCTL_UVCOUNTSHIFT) |
MBX1_ISPTSPCTL_OBJTYPE_OPAQUE |
MBX1_ISPTSPCTL_DCMPMODEALWAYS |
MBX1_ISPTSPCTL_VTXORDERSTRIP;
#else
sTACtl3DState.dwISPTSPCtl = MBX1_ISPTSPCTL_SRCBLENDONE |
MBX1_ISPTSPCTL_DESTBLENDZERO |
MBX1_ISPTSPCTL_LOGICALOPDISABLE |
MBX1_ISPTSPCTL_CKDISABLE |
(0 << MBX1_ISPTSPCTL_NUMPASSESSHIFT)|
(0 << MBX1_ISPTSPCTL_UVCOUNTSHIFT) |
MBX1_ISPTSPCTL_OBJTYPE_OPAQUE |
MBX1_ISPTSPCTL_DCMPMODEALWAYS |
MBX1_ISPTSPCTL_VTXORDERSTRIP;
#endif
sTACtl3DState.dwTSPObjCtl = MBX1_TSPOBJ_ACMPMODEALWAYS;
#if defined (SUPPORT_VGP) || defined (SUPPORT_VGP_LITE)
sTACtl3DState.dwFPFormat = psContext->dwNativeFPFormat;
dwStateChanged = MBX1_TASTATEPRES_FP_INPUTFORMAT;
#endif
dwStateChanged |= (MBX1_TASTATEPRES_ISPCTL |
MBX1_TASTATEPRES_TSPCTL);
/*
Disable tag-writes if not clearing the render-target
*/
if (!(dwFlags & D3DMCLEAR_TARGET))
{
sTACtl3DState.dwISPTSPCtl |= MBX1_ISPTSPCTL_TAGWDISABLE;
}
/*
Disable depth-writes if not clearing the depth-buffer
*/
if (!(dwFlags & D3DMCLEAR_ZBUFFER))
{
sTACtl3DState.dwISPTSPCtl |= MBX1_ISPTSPCTL_DWDISABLE;
}
/*
Set the required TA-ctl/3D state
*/
TACSWriteTACtlAnd3DState(psContext,
dwStateChanged,
&sTACtl3DState,
FALSE);
/*
Record which state we have changed
*/
psContext->sHWStateCtl.dwTACtl3DStateChanged |= dwStateChanged;
/*
zbuffer depthclears - default case - put depth clear 0-1 value into z
and rhw = 1.0 for correct untextured shading
*/
ntvFillDepth = FL2NTV(fFillDepth);
dwDepth = TO_ULONG(ntvFillDepth);
dwRHW = TO_ULONG(ntvD3DM_One);
/*
Depth clears - all handled as W-buffered.
*/
if(dwFlags & D3DMCLEAR_ZBUFFER)
{
/*
Fix for Rogue Squadron, that changes Wnear and Wfar midscene.
We put background at infinity hence use min float as RHW
*/
if (fFillDepth > 0.9999f)
{
/* Min float */
fFillDepth = 1.1754944e-038f;
}
else
{
D3DM_DPF((DPF_MESSAGE, "wbuffered clear depth %#8.8lX",FLOAT_TO_LONG(fFillDepth)));
/*
Clear depth is normalised W value between 0 -> 1,
(eye space - post projection, pre-perspective divide),
with 0.0 at near clip depth & 1.0 at far clip.
=> must use WNear & WFar to scale clear W (depth) to
original range between WNear & WFar.
(wnear & wfar values are the same as the near/far clip depths used to
construct the projection matrix, where wnear < wfar)
*/
fFillDepth = (fFillDepth * (NTV2FL(psContext->sTState.WFar) - NTV2FL(psContext->sTState.WNear))) +
NTV2FL(psContext->sTState.WNear);
D3DM_DPF((DPF_MESSAGE, " scaled depth %#8.8lX", FLOAT_TO_LONG(fFillDepth)));
/*
Now we must convert it to rhw (= 1 / Wscaled),
so its in the same space as the 3d data.
(The TA will take rhw in each vtx and put it
into the z field of each vtx output to core 3d,
for depth comparison)
*/
if(fFillDepth == 0.0f)
{
/*
Instead of divide by zero, return max float value #
*/
fFillDepth = FLT_MAX;
}
else
{
fFillDepth = NTV2FL(Div(D3DM_One, FL2NTV(fFillDepth)));
}
}
D3DM_DPF((DPF_MESSAGE, " rhw = 1/w %#8.8lX", FLOAT_TO_LONG(fFillDepth)));
ntvFillDepth = FL2NTV(fFillDepth);
dwRHW = TO_ULONG(ntvFillDepth);
}
/*
Go through each rectangle.
*/
for (i = 0; i < dwNumRects ; i++)
{
/*
Are we fullscreen?
*/
if (dwFSFlags & (0x1 << i))
{
D3DM_DPF((DPF_MESSAGE, "full render srf clear"));
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -