📄 tsstate.c
字号:
DWORD dwArg2;
DWORD dwColourOpLCtl3;
DWORD dwAlphaOpLCtl3;
DWORD dwMipFilterCtl;
DWORD dwLCtl1;
DWORD dwLCtl2;
DWORD dwLCtl3;
/* Stop if this stage is disabled */
if (!(psContext->dwFlags & (D3DM_CONTEXT_SWFLAGS_LAYER0ENABLED << i)))
{
break;
}
psLState = &psContext->sTState.sLState[i];
psTexture = psLState->psSurfData;
psHWLState = &psTACtl3DState->sTSPLState[i];
/*
Get the partially-setup HW texture-layer control words for this
D3D stage
NB: Word3 holds texture-blending controls only and is completely
setup here based on the chosen D3D colour/alpha ops'n'args.
*/
dwLCtl1 = psLState->sTSPLState.dwLCtl1;
dwLCtl2 = psLState->sTSPLState.dwLCtl2;
dwLCtl3 = 0;
/*
Update the HW mipmap-filtering mode
Enable if textured, the bound texture is a mipmap, and mipmapping
is not globally disabled.
*/
dwMipFilterCtl = MBX1_TSPPL2_MIPCTLNOTMIPMAP;
if(psTexture)
{
if((psTexture->sDescription.sTexture.psMapDetails->dwSuppliedLevels > 1) &&
(!(psContext->sRegData.dwFlags2 & D3DMREG2_DISABLE_MIPMAP)))
{
dwMipFilterCtl = psLState->dwMipFilterCtl;
}
}
dwLCtl2 &= MBX1_TSPPL2_MIPCTLCLRMASK;
dwLCtl2 |= dwMipFilterCtl;
/* Setup the appropriate mipmap-level clamp if mipmapping is in-use */
dwLCtl1 &= MBX1_TSPPL1_MIPMAPCLAMPCLRMASK;
if(dwMipFilterCtl != MBX1_TSPPL2_MIPCTLNOTMIPMAP)
{
DWORD dwMipLevels;
/* Get Number of Supplied Mip Map levels */
dwMipLevels = psTexture->sDescription.sTexture.psMapDetails->dwSuppliedLevels;
dwMipLevels -= psLState->dwMaxMipLevel;
if(dwMipLevels > 1)
{
DWORD dwLevelClamp;
dwLevelClamp = dwMipLevels - 1;
if(dwLevelClamp > ((~MBX1_TSPPL1_MIPMAPCLAMPCLRMASK) >> MBX1_TSPPL1_MIPMAPCLAMPSHIFT))
{
dwLevelClamp = (~MBX1_TSPPL1_MIPMAPCLAMPCLRMASK) >> MBX1_TSPPL1_MIPMAPCLAMPSHIFT;
}
dwLCtl1 |= dwLevelClamp << MBX1_TSPPL1_MIPMAPCLAMPSHIFT;
}
}
/*
Enable HW texture super-sampling to improved filtering when
anisotropic is requires.
NB: Anisotropic filtering depends on the filtermode and maximum
anisotropy level. Only required if both are valid.
*/
if ((psLState->dwLFlags & (LTSTATE_FLAGS_ANISOFILTERINGREQ |
LTSTATE_FLAGS_MAXANISOLEVELNOTONE))
== (LTSTATE_FLAGS_ANISOFILTERINGREQ |
LTSTATE_FLAGS_MAXANISOLEVELNOTONE)
#if defined (FIX_HW_PRN_530)
/* if supersample is enabled on one layer, enable on all */
|| (bTextureSuperSampleUsed == IMG_TRUE))
{
bTextureSuperSampleUsed = IMG_TRUE;
#else
)
{
#endif
#if defined (FIX_HW_PRN_734)
if(psContext->sHWState.sTACtl3DState.dwISPTSPCtl & MBX1_ISPTSPCTL_OFFSET)
{
/* If offset is present don't enable supersampling */
dwLCtl1 &= ~MBX1_TSPPL1_TSUPERSAMPLE;
}
else
{
dwLCtl1 |= MBX1_TSPPL1_TSUPERSAMPLE;
}
#else
dwLCtl1 |= MBX1_TSPPL1_TSUPERSAMPLE;
#endif
}
else
{
dwLCtl1 &= ~MBX1_TSPPL1_TSUPERSAMPLE;
}
/*
Lookup the HW state for the chosen D3D colour-op and args
NB: We clear some bits of the texture argument flags, in case
SPECULAR has been chosen. If the stage has been validated
it should have failed - if not, clearing the bits will
safely set the choice to DIFFUSE.
*/
dwArg1 = psLState->dwCArg1 & (D3DMTA_TFACTOR |
D3DMTA_COMPLEMENT |
D3DMTA_ALPHAREPLICATE);
dwArg2 = psLState->dwCArg2 & (D3DMTA_TFACTOR |
D3DMTA_COMPLEMENT |
D3DMTA_ALPHAREPLICATE);
dwColourOpLCtl3 = GetColourOpLCtl3(psLState->dwCOp,
dwArg1,
dwArg2,
psLState->dwArgTransFlags);
if (dwColourOpLCtl3 != 0xffffffff)
{
dwLCtl3 |= dwColourOpLCtl3;
}
/*
DotProd3 blending requires a change to the layer one control
word and the alpha channel blend to be in a known state.
*/
if (psLState->dwCOp == D3DMTOP_DOTPRODUCT3)
{
dwLCtl1 |= MBX1_TSPPL1_CSUM;
/*
When DotProd3 blending, the CSUM(CS1 * CS2) result is copied
from the colour blend to replace the (AS1 * AS2) blend in the
alpha channel. The (AS3 * AS4) blend must then be zero.
*/
dwLCtl3 |= MBX1_TSPPL3_AS1SELONE |
MBX1_TSPPL3_AS2SELDIFFUSEALPHA |
MBX1_TSPPL3_AS3SELONE |
MBX1_TSPPL3_INVAS3 |
MBX1_TSPPL3_ABEOP1X;
}
else
{
/*
Lookup the HW state for the chosen D3D alpha-op and args
NB: We clear some bits of the texture argument flags, in
case SPECULAR has been chosen. If the stage has been
validated it should have failed - if not, clearing the
bits will safely set the choice to DIFFUSE.
*/
dwArg1 = psLState->dwAArg1 & (D3DMTA_TFACTOR |
D3DMTA_COMPLEMENT |
D3DMTA_ALPHAREPLICATE);
dwArg2 = psLState->dwAArg2 & (D3DMTA_TFACTOR |
D3DMTA_COMPLEMENT |
D3DMTA_ALPHAREPLICATE);
dwAlphaOpLCtl3 = GetAlphaOpLCtl3(psLState->dwAOp,
dwArg1,
dwArg2,
psLState->dwArgTransFlags);
if (dwAlphaOpLCtl3 != 0xffffffff)
{
dwLCtl3 |= dwAlphaOpLCtl3;
}
}
/*
See if TextureAlpha is being used.
Used to work out if we really need Alpha Test enabled.
*/
if (psTexture)
{
if (!(psLState->dwArgTransFlags & PVR_ARGTRANSFLAG_OPAQUETEXTURE))
{
if (
((dwLCtl3 & (~MBX1_TSPPL3_AS1SELCLRMASK)) == MBX1_TSPPL3_AS1SELTEXTUREALPHA) |
((dwLCtl3 & (~MBX1_TSPPL3_AS2SELCLRMASK)) == MBX1_TSPPL3_AS2SELTEXTUREALPHA) |
((dwLCtl3 & (~MBX1_TSPPL3_AS3SELCLRMASK)) == MBX1_TSPPL3_AS3SELTEXTUREALPHA) |
((dwLCtl3 & (~MBX1_TSPPL3_AS4SELCLRMASK)) == MBX1_TSPPL3_AS4SELTEXTUREALPHA) |
((dwLCtl3 & (~MBX1_TSPPL3_CS2SELCLRMASK)) == MBX1_TSPPL3_CS2SELTEXTUREALPHA) |
((dwLCtl3 & (~MBX1_TSPPL3_CS4SELCLRMASK)) == MBX1_TSPPL3_CS4SELTEXTUREALPHA)
)
{
psContext->dwFlags |= D3DM_CONTEXT_SWFLAGS_USESTEXTUREALPHA;
}
}
}
else
{
psContext->dwFlags |= D3DM_CONTEXT_SWFLAGS_USESTEXTUREALPHA;
/*
Layer is Untextured. Check if it is trying to use a texture
*/
if (
((dwLCtl3 & (~MBX1_TSPPL3_CS1SELCLRMASK)) == MBX1_TSPPL3_CS1SELTEXTURE) |
((dwLCtl3 & (~MBX1_TSPPL3_CS2SELCLRMASK)) == MBX1_TSPPL3_CS2SELTEXTURE) |
((dwLCtl3 & (~MBX1_TSPPL3_CS3SELCLRMASK)) == MBX1_TSPPL3_CS3SELTEXTURE) |
((dwLCtl3 & (~MBX1_TSPPL3_CS4SELCLRMASK)) == MBX1_TSPPL3_CS4SELTEXTURE)
)
{
/*
Referencing a texture. If not the first stage, simply
disable it. Otherwise, default to use the diffuse colour
and alpha - refrast behaviour
*/
#if 0 //FIXME: I'm sure we don't need to leave an enabled tstage here but
// uncomment if causes problems in state post processing
if (i)
{
psContext->dwFlags &= ~(D3DM_CONTEXT_SWFLAGS_LAYER0ENABLED << i);
break;
}
else
{
dwLCtl3 = MBX1_TSPPL3_CS2SELDIFFUSE |
MBX1_TSPPL3_CS1SELONE |
MBX1_TSPPL3_CS3SELONE |
MBX1_TSPPL3_INVCS3 |
MBX1_TSPPL3_AS2SELDIFFUSEALPHA |
MBX1_TSPPL3_AS1SELONE |
MBX1_TSPPL3_AS3SELONE |
MBX1_TSPPL3_INVAS3;
}
#else
psContext->dwFlags &= ~(D3DM_CONTEXT_SWFLAGS_LAYER0ENABLED << i);
break;
#endif
}
}
/*
Determine the number of passes required for this HW-layer
*/
if (dwMipFilterCtl == MBX1_TSPPL2_MIPCTLMIPFILTER)
{
dwPassesReq += 2;
}
else
{
dwPassesReq += 1;
}
/*
Redo D-Adjust (Mip LOD Bias).
Always do it, since the mipmap mipfilter (between-level) mode may
have changed, so we might need to bias the D-Adjust differently.
*/
SetupDAdjust(psContext, psLState->DAdjust, &dwLCtl2, (dwMipFilterCtl == MBX1_TSPPL2_MIPCTLMIPFILTER));
/*
Save the completed HW texture-layer state for the texture-stage,
and flag that is has been altered.
*/
psHWLState->dwLCtl1 = dwLCtl1;
psHWLState->dwLCtl2 = dwLCtl2;
psHWLState->dwLCtl3 = dwLCtl3;
psHWStateCtl->dwTACtl3DStateChanged |= MBX1_TASTATEPRES_LAYER0CTL << i;
}
/*
Record the number of enabled D3D stages
*/
psContext->sTState.dwNumEnabledLayers = i;
/*
Update the TSP pass and texture-layer counts in the ISP/TSP control-word
*/
psTACtl3DState->dwISPTSPCtl &= MBX1_ISPTSPCTL_NUMPASSESCLRMASK &
MBX1_ISPTSPCTL_UVCOUNTCLRMASK;
psTACtl3DState->dwISPTSPCtl |= (dwPassesReq << MBX1_ISPTSPCTL_NUMPASSESSHIFT) &
(~MBX1_ISPTSPCTL_NUMPASSESCLRMASK);
if (dwPassesReq)
{
psTACtl3DState->dwISPTSPCtl |= ((i-1) << MBX1_ISPTSPCTL_UVCOUNTSHIFT) &
(~MBX1_ISPTSPCTL_UVCOUNTCLRMASK);
}
/*
Flag this the ISP/TSP control word may have changed
*/
psHWStateCtl->dwTACtl3DStateChanged |= MBX1_TASTATEPRES_ISPCTL;
/*
Update the HW object type required (dependant upon
MBX1_SWFLAGS_USESTEXTUREALPHA flag)
*/
SetupObjectType(psContext);
D3DM_DPF((DPF_EXIT, "<-PostProcessTSState"));
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : D3DM_TSS_NOP
PURPOSE : Does nothing !
PARAMETERS : psContext - Current D3D context
psLState - Layer state
dwValue - Value to set
RETURNS :
</function>
------------------------------------------------------------------------------*/
void D3DM_TSS_NOP(LPD3DM_CONTEXT psContext, LPD3DM_TEXTURESTAGESTATE psState)
{
D3DM_DPF((DPF_ENTRY, "->D3DM_TSS_NOP"));
D3DM_DPF((DPF_STATE, "D3DM_TSS_NOP: (State %d): Stage %d: Value = 0x%08X", psState->State, psState->Stage, psState->Value));
D3DM_DPF((DPF_EXIT, "<-D3DM_TSS_NOP"));
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : D3DM_TSS_TextureMap
PURPOSE :
PARAMETERS : psContext - Current D3D context
psLState - Layer state to be applied to...
dwValue - Value to set
RETURNS :
</function>
------------------------------------------------------------------------------*/
void D3DM_TSS_TextureMap(LPD3DM_CONTEXT psContext,LPD3DM_TEXTURESTAGESTATE psState)
{
PMBX1_TSPLAYER_STATE psTSPLState;
LPD3DM_SURFACE psPrevTexture;
LPD3DM_SURFACE psTexture;
PMAP_DETAILS psMapDetails;
PLAYER_TSTATE psLState;
DWORD dwValue;
DWORD dwStage;
D3DM_DPF((DPF_ENTRY, "->D3DM_TSS_TextureMap"));
D3DM_DPF((DPF_STATE, "D3DM_TSS_TextureMap: Stage %d: Handle = 0x%08X", psState->Stage, psState->Value));
dwStage = (DWORD)psState->Stage;
psLState = &psContext->sTState.sLState[dwStage];
psTSPLState = &psLState->sTSPLState;
dwValue = psState->Value;
/*
Enable texture parameters, note this will be turned off
in primitive setup FN's if there are no textured layers.
*/
psContext->sHWStateCtl.dwTACtl3DStateChanged |= MBX1_TASTATEPRES_ISPCTL;
/*
Un-bind the current texture (if any) from this stage
*/
psPrevTexture = psLState->psSurfData;
if (psPrevTexture)
{
psMapDetails = psPrevTexture->sDescription.sTexture.psMapDetails;
if (psMapDetails)
{
psMapDetails->dwFlags &= ~(MAPDETAILSFLAGS_USEDINSTAGE0 << dwStage);
}
psLState->psSurfData = 0;
}
/* Get the new texture to be bound to this stage */
psTexture = (LPD3DM_SURFACE) dwValue;
/*
Ignore if untextured
*/
if (!psTexture)
{
return;
}
/*
Associate the new texture with this stage
*/
psLState->psSurfData = psTexture;
psMapDetails = psTexture->sDescription.sTexture.psMapDetails;
psMapDetails->dwFlags |= MAPDETAILSFLAGS_USEDINSTAGE0 << dwStage;
/*
Fill-out texture parameters (setup once when the texture is created)
that are independent of any other texture-blending state
*/
psTSPLState->dwLCtl1 &= MBX1_TSPPL1_TPIXFORMCLRMASK &
MBX1_TSPPL1_TUSIZECLRMASK &
MBX1_TSPPL1_TVSIZECLRMASK;
psTSPLState->dwLCtl1 |= psMapDetails->sTSPCtl.dwLCtl1;
psTSPLState->dwLCtl2 &= MBX1_TSPPL2_TEXADDRCLRMASK &
MBX1_TSPPL2_TEXSTRIDECLRMASK;
psTSPLState->dwLCtl2 |= psMapDetails->sTSPCtl.dwLCtl2;
/*
If this texture is opaque, update the colour/alphs arg translation
flags (so that TEXTUREALPHA is mapped to ONE).
*/
if (psMapDetails->dwFlags & MAPDETAILSFLAGS_OPAQUE)
{
psLState->dwArgTransFlags |= PVR_ARGTRANSFLAG_OPAQUETEXTURE;
}
else
{
psLState->dwArgTransFlags &= ~PVR_ARGTRANSFLAG_OPAQUETEXTURE;
}
#ifdef FIXME // Luma texture
/*
An 8-bit luma texture? Update the colour/alphs arg translation
flags so that TEXTUREALPHA is mapped to ONE
*/
if (
(psTexture->sPixelFormat.dwFlags & DDPF_LUMINANCE) &&
(psTexture->sPixelFormat.dwLuminanceBitCount == 8)
)
{
psLState->dwArgTransFlags |= PVR_ARGTRANSFLAG_OPAQUETEXTURE;
}
#endif
/*
An 8-bit alpha texture? Update the colour/alphs arg translation
flags so that TEXTURE is mapped to ZERO
*/
if(psTexture->eFormat == D3DMFMT_A8)
{
psLState->dwArgTransFlags |= PVR_ARGTRANSFLAG_NOTEXCOLOUR;
}
else
{
psLState->dwArgTransFlags &= ~PVR_ARGTRANSFLAG_NOTEXCOLOUR;
}
/*
For mipmaps we need to check if a max level has been set
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -