You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4723 lines
214 KiB
4723 lines
214 KiB
/******************************Module*Header**********************************\
|
|
*
|
|
* *******************
|
|
* * D3D SAMPLE CODE *
|
|
* *******************
|
|
*
|
|
* Module Name: d3dtxt.c
|
|
*
|
|
* Content: D3D texture setup
|
|
*
|
|
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
|
|
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
|
|
\*****************************************************************************/
|
|
|
|
#include "glint.h"
|
|
#include "dma.h"
|
|
#include "chroma.h"
|
|
#include "tag.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Some variables shared through this module (not globals)
|
|
// These are set up in _D3DChangeTextureP3RX.
|
|
|
|
// P3 has 16 texture map base address slots, numbered 0 to 15 hence ...
|
|
#define P3_TEX_MAP_MAX_LEVEL 15
|
|
|
|
typedef struct
|
|
{
|
|
DWORD dwTex0MipBase;
|
|
DWORD dwTex0MipMax;
|
|
DWORD dwTex0ActMaxLevel; // Controlled by D3DTSS_MAXMIPLEVEL, default 0
|
|
DWORD dwTex1MipBase;
|
|
DWORD dwTex1MipMax;
|
|
DWORD dwTex1ActMaxLevel; // Same for Texture 1
|
|
} P3_MIP_BASES;
|
|
|
|
#define TSSTATE(stageno,argno) \
|
|
( pContext->TextureStageState[stageno].m_dwVal[argno] )
|
|
#define TSSTATESELECT(stageno,argno) \
|
|
( TSSTATE(stageno,argno) & D3DTA_SELECTMASK )
|
|
#define TSSTATEINVMASK(stageno,argno) \
|
|
( TSSTATE(stageno,argno) & ~D3DTA_COMPLEMENT )
|
|
#define TSSTATEALPHA(stageno,argno) \
|
|
( TSSTATE(stageno,argno) & ~D3DTA_ALPHAREPLICATE )
|
|
|
|
#define IS_ALPHA_ARG 1
|
|
#define IS_COLOR_ARG 0
|
|
|
|
|
|
#if DX8_DDI
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// __TXT_MapDX8toDX6TexFilter
|
|
//
|
|
// map DX8 enums into DX6(&7) texture filtering enums
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
DWORD
|
|
__TXT_MapDX8toDX6TexFilter( DWORD dwStageState, DWORD dwValue )
|
|
{
|
|
switch (dwStageState)
|
|
{
|
|
case D3DTSS_MAGFILTER:
|
|
switch (dwValue)
|
|
{
|
|
case D3DTEXF_POINT : return D3DTFG_POINT;
|
|
case D3DTEXF_LINEAR : return D3DTFG_LINEAR;
|
|
case D3DTEXF_FLATCUBIC : return D3DTFG_FLATCUBIC;
|
|
case D3DTEXF_GAUSSIANCUBIC : return D3DTFG_GAUSSIANCUBIC;
|
|
case D3DTEXF_ANISOTROPIC : return D3DTFG_ANISOTROPIC;
|
|
}
|
|
break;
|
|
case D3DTSS_MINFILTER:
|
|
switch (dwValue)
|
|
{
|
|
case D3DTEXF_POINT : return D3DTFN_POINT;
|
|
case D3DTEXF_LINEAR : return D3DTFN_LINEAR;
|
|
case D3DTEXF_FLATCUBIC : return D3DTFN_ANISOTROPIC;
|
|
}
|
|
break;
|
|
case D3DTSS_MIPFILTER:
|
|
switch (dwValue)
|
|
{
|
|
case D3DTEXF_NONE : return D3DTFP_NONE;
|
|
case D3DTEXF_POINT : return D3DTFP_POINT;
|
|
case D3DTEXF_LINEAR : return D3DTFP_LINEAR;
|
|
}
|
|
break;
|
|
}
|
|
return 0x0;
|
|
} // __TXT_MapDX8toDX6TexFilter
|
|
#endif // DX8_DDI
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// _D3D_TXT_ParseTextureStageStates
|
|
//
|
|
// Parse the texture state stages command token and update our context state
|
|
//
|
|
// Note : bTranslateDX8FilterValueToDX6 will only be FALSE when it is called
|
|
// from _D3D_SB_ExecuteStateSet if that state set's value has been
|
|
// changes by _D3D_SB_CaptureStateSet (Basically DX6 filter values are
|
|
// stored in the state set directly, thus no need to translate them.)
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
_D3D_TXT_ParseTextureStageStates(
|
|
P3_D3DCONTEXT* pContext,
|
|
D3DHAL_DP2TEXTURESTAGESTATE *pState,
|
|
DWORD dwCount,
|
|
BOOL bTranslateDX8FilterValueToDX6)
|
|
{
|
|
DWORD i;
|
|
DWORD dwStage, dwState, dwValue;
|
|
|
|
DISPDBG((DBGLVL,"*** In _D3D_TXT_ParseTextureStageStates"));
|
|
|
|
for (i = 0; i < dwCount; i++, pState++)
|
|
{
|
|
dwStage = pState->wStage;
|
|
dwState = pState->TSState;
|
|
dwValue = pState->dwValue;
|
|
|
|
// check for range before continuing
|
|
if ( (dwStage < D3DHAL_TSS_MAXSTAGES) &&
|
|
(dwState < D3DTSS_MAX))
|
|
{
|
|
|
|
#if DX7_D3DSTATEBLOCKS
|
|
if (pContext->bStateRecMode)
|
|
{
|
|
// Record this texture stage state into the
|
|
//current state set being recorded
|
|
_D3D_SB_RecordStateSetTSS(pContext, dwStage, dwState, dwValue);
|
|
|
|
// skip any further processing and go to the next TSS
|
|
continue;
|
|
}
|
|
#endif //DX7_D3DSTATEBLOCKS
|
|
|
|
#if DX7_TEXMANAGEMENT
|
|
if ((D3DTSS_TEXTUREMAP == dwState) && (0 != dwValue))
|
|
{
|
|
P3_SURF_INTERNAL* pTexture;
|
|
|
|
pTexture = GetSurfaceFromHandle(pContext, dwValue);
|
|
|
|
// If this is a valid managed texture
|
|
if (CHECK_SURF_INTERNAL_AND_DDSURFACE_VALIDITY(pTexture) &&
|
|
(pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
|
|
{
|
|
// Update stats
|
|
_D3D_TM_STAT_Inc_NumTexturesUsed(pContext);
|
|
_D3D_TM_STAT_Inc_NumUsedTexInVid(pContext, pTexture);
|
|
}
|
|
}
|
|
#endif // DX7_TEXMANAGEMENT
|
|
|
|
DISPDBG((DBGLVL," Stage = %d, State = 0x%x, Value = 0x%x",
|
|
dwStage, dwState, dwValue));
|
|
|
|
// Special case a texture handle change and the address update
|
|
switch ( dwState )
|
|
{
|
|
case D3DTSS_TEXTUREMAP:
|
|
DISPDBG((DBGLVL," D3DTSS_TEXTUREMAP: Handle=0x%x", dwValue));
|
|
|
|
if (pContext->TextureStageState[dwStage].m_dwVal[dwState] !=
|
|
dwValue)
|
|
{
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] =
|
|
dwValue;
|
|
DIRTY_TEXTURE(pContext);
|
|
}
|
|
break;
|
|
|
|
case D3DTSS_ADDRESS:
|
|
DISPDBG((DBGLVL," D3DTSS_ADDRESS"));
|
|
// map single set ADDRESS to both U and V controls
|
|
pContext->TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSU] =
|
|
pContext->TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSV] =
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
|
|
|
|
DIRTY_TEXTURE(pContext);
|
|
break;
|
|
|
|
case D3DTSS_COLOROP:
|
|
case D3DTSS_ALPHAOP:
|
|
case D3DTSS_COLORARG1:
|
|
case D3DTSS_COLORARG2:
|
|
case D3DTSS_ALPHAARG1:
|
|
case D3DTSS_ALPHAARG2:
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
|
|
pContext->Flags &= ~SURFACE_MODULATE;
|
|
DIRTY_TEXTURESTAGEBLEND(pContext);
|
|
DIRTY_TEXTURE(pContext);
|
|
break;
|
|
|
|
case D3DTSS_TEXCOORDINDEX:
|
|
DISPDBG((DBGLVL," D3DTSS_TEXCOORDINDEX: stage %d, value %d",
|
|
dwStage, dwValue ));
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
|
|
|
|
// Update the offsets to the texture coordinates
|
|
// NOTE: The texture coordinate index can contain various flags
|
|
// in addition to the actual value. These flags are:
|
|
// D3DTSS_TCI_PASSTHRU (default - resolves to zero)
|
|
// D3DTSS_TCI_CAMERASPACENORMAL
|
|
// D3DTSS_TCI_CAMERASPACEPOSITION
|
|
// D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
|
|
// and are used for texture coordinate generation.
|
|
//
|
|
// These flags are not relevant when considering the offset of
|
|
// texture coordinates in the vertex stream. These flags appear
|
|
// in the high word of the index value DWORD. Only the low word
|
|
// contains actual index data. Therefore, we will mask of the
|
|
// low word when looking up the offset table for this texture
|
|
// coordinate index.
|
|
pContext->FVFData.dwTexOffset[dwStage] =
|
|
pContext->FVFData.dwTexCoordOffset[dwValue & 0x0000FFFFul];
|
|
|
|
DIRTY_TEXTURE(pContext);
|
|
break;
|
|
|
|
case D3DTSS_MIPMAPLODBIAS:
|
|
DISPDBG((DBGLVL," D3DTSS_MIPMAPLODBIAS: stage %d, value %d",
|
|
dwStage, dwValue ));
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
|
|
DIRTY_TEXTURE(pContext);
|
|
break;
|
|
|
|
case D3DTSS_MAGFILTER:
|
|
case D3DTSS_MINFILTER:
|
|
case D3DTSS_MIPFILTER:
|
|
#if DX8_DDI
|
|
if((!IS_DX7_OR_EARLIER_APP(pContext)) &&
|
|
bTranslateDX8FilterValueToDX6)
|
|
{
|
|
// filtering values are somewhat different in DX8
|
|
// so translate them before using them.
|
|
dwValue = __TXT_MapDX8toDX6TexFilter(dwState, dwValue);
|
|
}
|
|
#endif DX8_DDI
|
|
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
|
|
DIRTY_TEXTURE(pContext);
|
|
break;
|
|
|
|
case D3DTSS_MAXMIPLEVEL:
|
|
DISPDBG((DBGLVL," D3DTSS_MAXMIPLEVEL: stage %d, value %d",
|
|
dwStage, dwValue ));
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
|
|
DIRTY_TEXTURE(pContext);
|
|
break;
|
|
|
|
default:
|
|
pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
|
|
DIRTY_TEXTURE(pContext);
|
|
break;
|
|
} // switch
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((WRNLVL,"Out of range stage/state %d %d",dwStage,dwState));
|
|
}// if
|
|
} // for
|
|
} // _D3D_TXT_ParseTextureStageStates
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SETARG
|
|
//
|
|
// dwArg = the argument.
|
|
// num = argument number (1 or 2).
|
|
// bIsAlpha = TRUE if this is the alpha channel,
|
|
// FALSE if this is the colour channel.
|
|
// iD3DStage = D3D stage number.
|
|
// iChipStageNo = chip stage number (should only be 0 or 1 on P3)
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
SETARG(
|
|
P3_D3DCONTEXT *pContext,
|
|
struct TextureCompositeRGBAMode *pMode,
|
|
DWORD dwArg,
|
|
DWORD num,
|
|
BOOL bIsAlpha,
|
|
DWORD iD3DStage,
|
|
DWORD iChipStageNo)
|
|
{
|
|
BOOL bSetArgToggleInvert;
|
|
DWORD dwArgValue, dwInvertArgValue;
|
|
BOOL bArgValueAssigned = FALSE,
|
|
bInvertArgValueAssigned;
|
|
|
|
bSetArgToggleInvert = FALSE;
|
|
switch (dwArg & D3DTA_SELECTMASK)
|
|
{
|
|
case D3DTA_TEXTURE:
|
|
if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
|
|
{
|
|
dwArgValue = ( pContext->iStageTex[iD3DStage] == 0 ) ?
|
|
P3RX_TEXCOMP_T0A :
|
|
P3RX_TEXCOMP_T1A;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," Tex%dA", pContext->iStageTex[iD3DStage] ));
|
|
}
|
|
else
|
|
{
|
|
dwArgValue = ( pContext->iStageTex[iD3DStage] == 0 ) ?
|
|
P3RX_TEXCOMP_T0C :
|
|
P3RX_TEXCOMP_T1C;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," Tex%dC", pContext->iStageTex[iD3DStage] ));
|
|
}
|
|
break;
|
|
|
|
case D3DTA_DIFFUSE:
|
|
if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_CA;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," DiffA" ));
|
|
}
|
|
else
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_CC;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," DiffC" ));
|
|
}
|
|
break;
|
|
|
|
case D3DTA_CURRENT:
|
|
// Cope with a "current" argument in texcomp0
|
|
if ( iChipStageNo == 0 )
|
|
{
|
|
// This is texcomp0
|
|
if ( pContext->bBumpmapEnabled )
|
|
{
|
|
// Emboss bumpmapping is on
|
|
if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
|
|
{
|
|
// This is the alpha-channel, where the D3D stages 0 & 1
|
|
// should have put the heightfield info.
|
|
dwArgValue = P3RX_TEXCOMP_HEIGHTA;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," BumpA" ));
|
|
// And cope with inverted bumpmaps.
|
|
bSetArgToggleInvert = pContext->bBumpmapInverted;
|
|
}
|
|
else
|
|
{
|
|
// Colour channel - this will hold the diffuse colour.
|
|
dwArgValue = P3RX_TEXCOMP_CC;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," DiffC" ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Embossing is off - default to diffuse.
|
|
if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_CA;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," DiffA" ));
|
|
}
|
|
else
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_CC;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," DiffC" ));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// texcomp stage 1
|
|
if ( pContext->bStage0DotProduct )
|
|
{
|
|
// Need to take the dotproduct sum result,
|
|
// even in the alpha channel, according to the docs.
|
|
dwArgValue = P3RX_TEXCOMP_SUM;
|
|
bArgValueAssigned = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_OA;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," CurrA" ));
|
|
}
|
|
else
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_OC;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," CurrC" ));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case D3DTA_TFACTOR:
|
|
if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_FA;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," TfactA" ));
|
|
}
|
|
else
|
|
{
|
|
dwArgValue = P3RX_TEXCOMP_FC;
|
|
bArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," TfactC" ));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if ( bIsAlpha )
|
|
{
|
|
DISPDBG((ERRLVL,"ERROR: Invalid AlphaArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_ARG );
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"ERROR: Invalid ColorArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_ARG );
|
|
}
|
|
break;
|
|
} // switch
|
|
|
|
if ( ( (dwArg & D3DTA_COMPLEMENT) == 0 ) == bSetArgToggleInvert )
|
|
{
|
|
dwInvertArgValue= __PERMEDIA_ENABLE;
|
|
bInvertArgValueAssigned = TRUE;
|
|
DISPDBG((DBGLVL," inverted" ));
|
|
}
|
|
else
|
|
{
|
|
dwInvertArgValue = __PERMEDIA_DISABLE;
|
|
bInvertArgValueAssigned = TRUE;
|
|
}
|
|
|
|
// Set up the I input for MODULATExxx_ADDxxx modes.
|
|
if ( num == 1 )
|
|
{
|
|
switch (dwArg & D3DTA_SELECTMASK)
|
|
{
|
|
case D3DTA_TEXTURE:
|
|
pMode->I = ( pContext->iStageTex[iD3DStage] == 0 ) ?
|
|
P3RX_TEXCOMP_I_T0A :
|
|
P3RX_TEXCOMP_I_T1A;
|
|
DISPDBG((DBGLVL," I: Tex%dA", pContext->iStageTex[iD3DStage] ));
|
|
break;
|
|
|
|
case D3DTA_DIFFUSE:
|
|
pMode->I = P3RX_TEXCOMP_I_CA;
|
|
DISPDBG((DBGLVL," I: DiffA" ));
|
|
break;
|
|
|
|
case D3DTA_CURRENT:
|
|
if ( iChipStageNo == 0 )
|
|
{
|
|
if ( pContext->bBumpmapEnabled )
|
|
{
|
|
// Bumpmapping mode.
|
|
pMode->I = P3RX_TEXCOMP_I_HA;
|
|
DISPDBG((DBGLVL," I: BumpA" ));
|
|
}
|
|
else
|
|
{
|
|
pMode->I = P3RX_TEXCOMP_I_CA;
|
|
DISPDBG((DBGLVL," I: DiffA" ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMode->I = P3RX_TEXCOMP_I_OA;
|
|
DISPDBG((DBGLVL," I: CurrA" ));
|
|
}
|
|
break;
|
|
|
|
case D3DTA_TFACTOR:
|
|
pMode->I = P3RX_TEXCOMP_I_FA;
|
|
DISPDBG((DBGLVL," I: TfactA" ));
|
|
break;
|
|
|
|
default:
|
|
if ( bIsAlpha )
|
|
{
|
|
DISPDBG((ERRLVL,"ERROR: Invalid AlphaArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_ARG );
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"ERROR: Invalid ColorArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_ARG );
|
|
}
|
|
break;
|
|
} // switch
|
|
|
|
if ( ( (dwArg & D3DTA_COMPLEMENT) == 0 ) == bSetArgToggleInvert )
|
|
{
|
|
pMode->InvertI = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
pMode->InvertI = __PERMEDIA_DISABLE;
|
|
}
|
|
} // if ( num == 1 )
|
|
|
|
if (bArgValueAssigned)
|
|
{
|
|
if (num == 1)
|
|
{
|
|
pMode->Arg1 = dwArgValue;
|
|
}
|
|
else
|
|
{
|
|
pMode->Arg2 = dwArgValue;
|
|
}
|
|
}
|
|
|
|
if (bInvertArgValueAssigned)
|
|
{
|
|
if (num == 1)
|
|
{
|
|
pMode->InvertArg1 = dwInvertArgValue;
|
|
}
|
|
else
|
|
{
|
|
pMode->InvertArg2 = dwInvertArgValue;
|
|
}
|
|
}
|
|
} // SETARG
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SETTAARG_ALPHA
|
|
//
|
|
// TexApp blend mode for the alpha channel.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
SETTAARG_ALPHA(
|
|
P3_D3DCONTEXT *pContext,
|
|
struct TextureApplicationMode *pMode,
|
|
DWORD dwArg,
|
|
DWORD num)
|
|
{
|
|
switch (dwArg & D3DTA_SELECTMASK)
|
|
{
|
|
case D3DTA_TEXTURE:
|
|
DISPDBG((ERRLVL,"ERROR: Invalid TA AlphaArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
|
|
break;
|
|
case D3DTA_DIFFUSE:
|
|
if ( (num) == 1 )
|
|
{
|
|
pMode->AlphaA = P3RX_TEXAPP_A_CA;
|
|
DISPDBG((DBGLVL," DiffA" ));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"ERROR: Invalid TA AlphaArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
|
|
}
|
|
break;
|
|
case D3DTA_CURRENT:
|
|
if ( (num) == 2 )
|
|
{
|
|
pMode->AlphaB = P3RX_TEXAPP_B_TA;
|
|
DISPDBG((DBGLVL," CurrA" ));
|
|
}
|
|
else
|
|
{
|
|
// Can't do
|
|
DISPDBG((ERRLVL,"ERROR: Invalid TA AlphaArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
|
|
}
|
|
break;
|
|
case D3DTA_TFACTOR:
|
|
if ( (num) == 1 )
|
|
{
|
|
pMode->AlphaA = P3RX_TEXAPP_A_KA;
|
|
DISPDBG((DBGLVL," TfactA" ));
|
|
}
|
|
else
|
|
{
|
|
if ( (num) != 2)
|
|
{
|
|
DISPDBG((ERRLVL," ** SETTAARG: num must be 1 or 2"));
|
|
}
|
|
pMode->AlphaB = P3RX_TEXAPP_B_KA;
|
|
DISPDBG((DBGLVL," TfactA" ));
|
|
}
|
|
break;
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown TA AlphaArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_ARG );
|
|
break;
|
|
}
|
|
|
|
if ( (dwArg & D3DTA_COMPLEMENT) != 0 )
|
|
{
|
|
// Can't do COMPLEMENT on the args.
|
|
DISPDBG((ERRLVL,"ERROR: Can't do COMPLEMENT in TA unit"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
|
|
}
|
|
} // SETTAARG_ALPHA
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SETTAARG_COLOR
|
|
//
|
|
// TexApp blend mode for the color channel.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
SETTAARG_COLOR(
|
|
P3_D3DCONTEXT *pContext,
|
|
struct TextureApplicationMode *pMode,
|
|
DWORD dwArg,
|
|
DWORD num)
|
|
{
|
|
switch (dwArg & D3DTA_SELECTMASK)
|
|
{
|
|
DISPDBG((ERRLVL,"ERROR: Invalid TA ColorArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
|
|
break;
|
|
case D3DTA_DIFFUSE:
|
|
if ( (num) == 1 )
|
|
{
|
|
if ( (dwArg & D3DTA_ALPHAREPLICATE) != 0 )
|
|
{
|
|
pMode->ColorA = P3RX_TEXAPP_A_CA;
|
|
DISPDBG((DBGLVL," DiffA" ));
|
|
}
|
|
else
|
|
{
|
|
pMode->ColorA = P3RX_TEXAPP_A_CC;
|
|
DISPDBG((DBGLVL," DiffC" ));
|
|
}
|
|
// Set up the I input for MODULATExxx_ADDxxx modes
|
|
pMode->ColorI = P3RX_TEXAPP_I_CA;
|
|
DISPDBG((DBGLVL," I: DiffA" ));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"ERROR: Invalid TA ColorArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
|
|
}
|
|
break;
|
|
case D3DTA_CURRENT:
|
|
if ( (num) == 2 )
|
|
{
|
|
if (dwArg & D3DTA_ALPHAREPLICATE)
|
|
{
|
|
pMode->ColorB = P3RX_TEXAPP_B_TA;
|
|
DISPDBG((DBGLVL," CurrA" ));
|
|
}
|
|
else
|
|
{
|
|
pMode->ColorB = P3RX_TEXAPP_B_TC;
|
|
DISPDBG((DBGLVL," CurrC" ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Can't do.
|
|
DISPDBG((ERRLVL,"ERROR: Invalid TA ColorArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
|
|
}
|
|
break;
|
|
case D3DTA_TFACTOR:
|
|
if ( (num) == 1 )
|
|
{
|
|
if ( (dwArg & D3DTA_ALPHAREPLICATE) != 0 )
|
|
{
|
|
pMode->ColorA = P3RX_TEXAPP_A_KA;
|
|
DISPDBG((DBGLVL," TfactA" ));
|
|
}
|
|
else
|
|
{
|
|
pMode->ColorA = P3RX_TEXAPP_A_KC;
|
|
DISPDBG((DBGLVL," TfactC" ));
|
|
}
|
|
// Set up the I input for MODULATExxx_ADDxxx modes.
|
|
pMode->ColorI = P3RX_TEXAPP_I_KA;
|
|
DISPDBG((DBGLVL," I: TfactA" ));
|
|
}
|
|
else
|
|
{
|
|
if ( (num) != 2)
|
|
{
|
|
DISPDBG((ERRLVL," ** SETTAARG: num must be 1 or 2"));
|
|
}
|
|
|
|
if (dwArg & D3DTA_ALPHAREPLICATE)
|
|
{
|
|
pMode->ColorB = P3RX_TEXAPP_B_KA;
|
|
DISPDBG((DBGLVL," TfactA" ));
|
|
}
|
|
else
|
|
{
|
|
pMode->ColorB = P3RX_TEXAPP_B_KC;
|
|
DISPDBG((DBGLVL," TfactC" ));
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown TA ColorArgument"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_ARG );
|
|
break;
|
|
}
|
|
if ( (dwArg & D3DTA_COMPLEMENT) != 0 )
|
|
{
|
|
// Can't do COMPLEMENT on the args.
|
|
DISPDBG((ERRLVL,"ERROR: Can't do COMPLEMENT in TA unit"));
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
|
|
}
|
|
} // SETTAARG_COLOR
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SETOP
|
|
//
|
|
// Note - SETOP must be done after SETARG for DISABLE to work.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
SETOP(
|
|
P3_D3DCONTEXT *pContext,
|
|
struct TextureCompositeRGBAMode* pMode,
|
|
DWORD dwOperation,
|
|
DWORD iD3DStage,
|
|
DWORD iChipStageNo,
|
|
BOOL bIsAlpha)
|
|
{
|
|
pMode->Enable = __PERMEDIA_ENABLE;
|
|
pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pMode->InvertI = __PERMEDIA_DISABLE;
|
|
pMode->A = P3RX_TEXCOMP_ARG1;
|
|
pMode->B = P3RX_TEXCOMP_ARG2;
|
|
switch (dwOperation)
|
|
{
|
|
case D3DTOP_DISABLE:
|
|
if ( bIsAlpha )
|
|
{
|
|
// Just pass through "current"
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
if ( iChipStageNo == 0 )
|
|
{
|
|
if ( pContext->bBumpmapEnabled )
|
|
{
|
|
// Embossing is on.
|
|
pMode->Arg1 = P3RX_TEXCOMP_HEIGHTA;
|
|
}
|
|
else
|
|
{
|
|
// Current = diffuse in stage0.
|
|
pMode->Arg1 = P3RX_TEXCOMP_CA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pContext->bStage0DotProduct )
|
|
{
|
|
pMode->Arg1 = P3RX_TEXCOMP_SUM;
|
|
}
|
|
else
|
|
{
|
|
pMode->Arg1 = P3RX_TEXCOMP_OA;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"SETOP: Colour op was DISABLE"
|
|
" - should never have got here."));
|
|
}
|
|
break;
|
|
|
|
case D3DTOP_SELECTARG1:
|
|
DISPDBG((DBGLVL," D3DTOP_SELECTARG1"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
break;
|
|
|
|
case D3DTOP_SELECTARG2:
|
|
DISPDBG((DBGLVL," D3DTOP_SELECTARG2"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A; // No Pass B
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
break;
|
|
|
|
case D3DTOP_MODULATE:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATE"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
|
|
break;
|
|
|
|
case D3DTOP_MODULATE2X:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATE2X"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
|
|
pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_TWO;
|
|
break;
|
|
|
|
case D3DTOP_MODULATE4X:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATE4X"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
|
|
pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_FOUR;
|
|
break;
|
|
|
|
case D3DTOP_ADD:
|
|
DISPDBG((DBGLVL," D3DTOP_ADD"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_ADD_AB;
|
|
break;
|
|
|
|
case D3DTOP_ADDSIGNED:
|
|
DISPDBG((DBGLVL," D3DTOP_ADDSIGNED"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_ADDSIGNED_AB;
|
|
break;
|
|
|
|
case D3DTOP_ADDSIGNED2X:
|
|
DISPDBG((DBGLVL," D3DTOP_ADDSIGNED2X"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_ADDSIGNED_AB;
|
|
pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_TWO;
|
|
break;
|
|
|
|
case D3DTOP_SUBTRACT:
|
|
DISPDBG((DBGLVL," D3DTOP_SUBTRACT"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_SUBTRACT_AB;
|
|
break;
|
|
|
|
case D3DTOP_ADDSMOOTH:
|
|
DISPDBG((DBGLVL," D3DTOP_ADDSMOOTH"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_ADD_AB_SUB_MODULATE_AB;
|
|
break;
|
|
|
|
case D3DTOP_BLENDDIFFUSEALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDDIFFUSEALPHA"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
pMode->I = P3RX_TEXCOMP_I_CA;
|
|
break;
|
|
|
|
case D3DTOP_BLENDTEXTUREALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDTEXTUREALPHA"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
pMode->I = ( pContext->iStageTex[iD3DStage] == 0 ) ?
|
|
P3RX_TEXCOMP_I_T0A :
|
|
P3RX_TEXCOMP_I_T1A;
|
|
DISPDBG((DBGLVL," alpha: Tex%dA", pContext->iStageTex[iD3DStage] ));
|
|
break;
|
|
|
|
case D3DTOP_BLENDFACTORALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDFACTORALPHA"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
pMode->I = P3RX_TEXCOMP_I_FA;
|
|
break;
|
|
|
|
case D3DTOP_BLENDCURRENTALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDCURRENTALPHA"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
pMode->I = P3RX_TEXCOMP_I_OA;
|
|
break;
|
|
|
|
case D3DTOP_BLENDTEXTUREALPHAPM:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDTEXTUREALPHAPM"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
pMode->I = ( pContext->iStageTex[iD3DStage] == 0 ) ?
|
|
P3RX_TEXCOMP_I_T0A :
|
|
P3RX_TEXCOMP_I_T1A;
|
|
DISPDBG((DBGLVL," alpha: Tex%dA", pContext->iStageTex[iD3DStage] ));
|
|
pMode->InvertI = __PERMEDIA_ENABLE;
|
|
break;
|
|
|
|
case D3DTOP_PREMODULATE:
|
|
DISPDBG((DBGLVL," D3DTOP_PREMODULATE"));
|
|
// result = current_tex * next_stage_tex - ignore arguments.
|
|
if ( ( pContext->iStageTex[iD3DStage] != -1 ) &&
|
|
( pContext->iStageTex[iD3DStage+1] != -1 ) )
|
|
{
|
|
pMode->Arg1 = ( pContext->iStageTex[iD3DStage] == 0 ) ?
|
|
P3RX_TEXCOMP_T0C :
|
|
P3RX_TEXCOMP_T1C;
|
|
DISPDBG((DBGLVL," Arg1: Tex%d", pContext->iStageTex[iD3DStage] ));
|
|
pMode->Arg2 = ( pContext->iStageTex[iD3DStage+1] == 0 ) ?
|
|
P3RX_TEXCOMP_T0C :
|
|
P3RX_TEXCOMP_T1C;
|
|
DISPDBG((DBGLVL," Arg2: Tex%d", pContext->iStageTex[iD3DStage+1] ));
|
|
}
|
|
else
|
|
{
|
|
// Not enough textures
|
|
DISPDBG((ERRLVL,"** SETOP: PREMODULATE didn't have two "
|
|
"textures to play with."));
|
|
if ( bIsAlpha )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_OP_HERE );
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_OP_HERE );
|
|
}
|
|
pMode->Arg1 = P3RX_TEXCOMP_CC;
|
|
pMode->Arg2 = P3RX_TEXCOMP_CC;
|
|
}
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
break;
|
|
|
|
case D3DTOP_MODULATEALPHA_ADDCOLOR:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATEALPHA_ADDCOLOR"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
// I input set up by SETARG
|
|
break;
|
|
|
|
case D3DTOP_MODULATECOLOR_ADDALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATECOLOR_ADDALPHA"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB_ADD_I;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
// I input set up by SETARG
|
|
break;
|
|
|
|
case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATEINVALPHA_ADDCOLOR"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
// I input set up by SETARG
|
|
pMode->InvertI = 1 - pMode->InvertI;
|
|
break;
|
|
|
|
case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATEINVCOLOR_ADDALPHA"));
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB_ADD_I;
|
|
pMode->A = P3RX_TEXCOMP_ARG2;
|
|
pMode->B = P3RX_TEXCOMP_ARG1;
|
|
pMode->InvertArg1 = 1 - pMode->InvertArg1;
|
|
// I input set up by SETARG
|
|
break;
|
|
|
|
case D3DTOP_DOTPRODUCT3:
|
|
DISPDBG((DBGLVL," D3DTOP_DOTPRODUCT3"));
|
|
if ( iChipStageNo == 0 )
|
|
{
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_SIGNED_AB;
|
|
// Signal that the special input to stage 1 is needed.
|
|
pContext->bStage0DotProduct = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Can't do stage 1 dotproduct. Fail.
|
|
DISPDBG((ERRLVL,"** SETOP: Can't do DOTPRODUCT3 in second stage."));
|
|
if ( bIsAlpha )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_OP_HERE );
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_OP_HERE );
|
|
}
|
|
pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
}
|
|
break;
|
|
|
|
case D3DTOP_BUMPENVMAP:
|
|
case D3DTOP_BUMPENVMAPLUMINANCE:
|
|
DISPDBG((ERRLVL,"** SETOP: Unsupported operation."));
|
|
if ( bIsAlpha )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_ALPHA_OP );
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_COLOR_OP );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"** SETOP: Unknown operation."));
|
|
if ( bIsAlpha )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_OP );
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_OP );
|
|
}
|
|
break;
|
|
} // switch
|
|
} // SETOP
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// SETTAOP
|
|
//
|
|
// Must be done after SETTAARG to set up DISABLE properly.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
SETTAOP(
|
|
P3_D3DCONTEXT *pContext,
|
|
struct TextureApplicationMode* pMode,
|
|
DWORD dwOperand,
|
|
BOOL bIsAlpha,
|
|
DWORD iD3DStage,
|
|
DWORD iChipStageNo)
|
|
{
|
|
DWORD dwInvertI, dwOperation, dwI = 0, dwA = 0;
|
|
BOOL bOperation = FALSE,
|
|
bI = FALSE,
|
|
bA = FALSE;
|
|
|
|
pMode->Enable = __PERMEDIA_ENABLE;
|
|
dwInvertI = __PERMEDIA_DISABLE;
|
|
switch (dwOperand)
|
|
{
|
|
case D3DTOP_DISABLE:
|
|
if ( bIsAlpha )
|
|
{
|
|
// Just pass through "current"
|
|
dwOperation = P3RX_TEXAPP_OPERATION_PASS_A;
|
|
bOperation = TRUE;
|
|
dwA = P3RX_TEXAPP_A_CA;
|
|
bA = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"SETTAOP: Colour op was DISABLE "
|
|
" should never have got here."));
|
|
}
|
|
break;
|
|
case D3DTOP_SELECTARG1:
|
|
DISPDBG((DBGLVL," D3DTOP_SELECTARG1"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_PASS_A;
|
|
bOperation = TRUE;
|
|
break;
|
|
case D3DTOP_SELECTARG2:
|
|
DISPDBG((DBGLVL," D3DTOP_SELECTARG2"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_PASS_B;
|
|
bOperation = TRUE;
|
|
break;
|
|
case D3DTOP_MODULATE:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATE"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_AB;
|
|
bOperation = TRUE;
|
|
break;
|
|
case D3DTOP_ADD:
|
|
DISPDBG((DBGLVL," D3DTOP_ADD"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_ADD_AB;
|
|
bOperation = TRUE;
|
|
break;
|
|
case D3DTOP_BLENDDIFFUSEALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDDIFFUSEALPHA"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_LERP_ABI;
|
|
bOperation = TRUE;
|
|
dwInvertI = 1 - dwInvertI;
|
|
dwI = P3RX_TEXAPP_I_CA;
|
|
bI = TRUE;
|
|
break;
|
|
case D3DTOP_BLENDFACTORALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDFACTORALPHA"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_LERP_ABI;
|
|
bOperation = TRUE;
|
|
dwInvertI = 1 - dwInvertI;
|
|
dwI = P3RX_TEXAPP_I_KA;
|
|
bI = TRUE;
|
|
break;
|
|
case D3DTOP_BLENDCURRENTALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_BLENDCURRENTALPHA"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_LERP_ABI;
|
|
bOperation = TRUE;
|
|
dwInvertI = 1 - dwInvertI;
|
|
dwI = P3RX_TEXAPP_I_TA;
|
|
bI = TRUE;
|
|
break;
|
|
case D3DTOP_MODULATEALPHA_ADDCOLOR:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATEALPHA_ADDCOLOR"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_BI_ADD_A;
|
|
bOperation = TRUE;
|
|
// I should have been set up by SETTAARG.
|
|
// dwI = P3RX_TEXAPP_I_TA;
|
|
break;
|
|
case D3DTOP_MODULATECOLOR_ADDALPHA:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATECOLOR_ADDALPHA"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_AB_ADD_I;
|
|
bOperation = TRUE;
|
|
// I should have been set up by SETTAARG.
|
|
// dwI = P3RX_TEXAPP_I_TA;
|
|
break;
|
|
case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
|
|
DISPDBG((DBGLVL," D3DTOP_MODULATEINVALPHA_ADDCOLOR"));
|
|
dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_BI_ADD_A;
|
|
bOperation = TRUE;
|
|
dwInvertI = 1 - dwInvertI;
|
|
// I should have been set up by SETTAARG.
|
|
// dwI = P3RX_TEXAPP_I_TA;
|
|
break;
|
|
case D3DTOP_MODULATE2X:
|
|
case D3DTOP_MODULATE4X:
|
|
case D3DTOP_ADDSIGNED:
|
|
case D3DTOP_ADDSIGNED2X:
|
|
case D3DTOP_SUBTRACT:
|
|
case D3DTOP_ADDSMOOTH:
|
|
case D3DTOP_BLENDTEXTUREALPHA:
|
|
case D3DTOP_BLENDTEXTUREALPHAPM:
|
|
case D3DTOP_PREMODULATE:
|
|
case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
|
|
case D3DTOP_DOTPRODUCT3:
|
|
DISPDBG((ERRLVL,"** SETTAOP: Unsupported operation in TA unit."));
|
|
if ( bIsAlpha )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_OP_HERE );
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_OP_HERE );
|
|
}
|
|
break;
|
|
case D3DTOP_BUMPENVMAP:
|
|
case D3DTOP_BUMPENVMAPLUMINANCE:
|
|
DISPDBG((ERRLVL,"** SETTAOP: Unsupported operation."));
|
|
if ( bIsAlpha )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_ALPHA_OP );
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_COLOR_OP );
|
|
}
|
|
break;
|
|
default:
|
|
// What is this?. //azn
|
|
DISPDBG((ERRLVL,"** SETTAOP: Unknown operation."));
|
|
if ( bIsAlpha )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_OP );
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_OP );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(bIsAlpha)
|
|
{
|
|
pMode->AlphaInvertI = dwInvertI;
|
|
if (bOperation)
|
|
{
|
|
pMode->AlphaOperation = dwOperation;
|
|
}
|
|
|
|
if (bI)
|
|
{
|
|
pMode->AlphaI = dwI;
|
|
}
|
|
|
|
if (bA)
|
|
{
|
|
pMode->AlphaA = dwA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMode->ColorInvertI = dwInvertI;
|
|
|
|
if (bOperation)
|
|
{
|
|
pMode->ColorOperation = dwOperation;
|
|
}
|
|
|
|
if (bI)
|
|
{
|
|
pMode->ColorI = dwI;
|
|
}
|
|
|
|
if (bA)
|
|
{
|
|
pMode->ColorA = dwA;
|
|
}
|
|
}
|
|
} // SETTAOP
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// _D3DDisplayWholeTSSPipe
|
|
//
|
|
// Dumps the whole TSS pipe state out to the debug stream.
|
|
// Also dumps fog, specular and alpha-blend state out.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void _D3DDisplayWholeTSSPipe ( P3_D3DCONTEXT* pContext, int iDebugNumber )
|
|
{
|
|
#if DBG
|
|
int i;
|
|
char *pszTemp, *pszTempPre, *pszTempPost;
|
|
char *pszOp;
|
|
char *pszArg1Pre, *pszArg1, *pszArg1Post;
|
|
char *pszArg2Pre, *pszArg2, *pszArg2Post;
|
|
char *pszSrc, *pszDest;
|
|
P3_SURF_INTERNAL* pTexture;
|
|
P3_SURF_FORMAT* pFormatSurface;
|
|
|
|
DISPDBG((iDebugNumber,"TSS dump:"));
|
|
|
|
#define SWITCH_ARG(prefix,opname) \
|
|
case prefix##_##opname##: pszTemp = #opname; break
|
|
|
|
i = 0;
|
|
while ( ( i < 8 ) && ( TSSTATE ( i, D3DTSS_COLOROP ) != D3DTOP_DISABLE ) )
|
|
{
|
|
|
|
switch ( TSSTATE ( i, D3DTSS_COLOROP ) )
|
|
{
|
|
SWITCH_ARG ( D3DTOP,DISABLE );
|
|
SWITCH_ARG ( D3DTOP,SELECTARG1 );
|
|
SWITCH_ARG ( D3DTOP,SELECTARG2 );
|
|
SWITCH_ARG ( D3DTOP,MODULATE );
|
|
SWITCH_ARG ( D3DTOP,MODULATE2X );
|
|
SWITCH_ARG ( D3DTOP,MODULATE4X );
|
|
SWITCH_ARG ( D3DTOP,ADD );
|
|
SWITCH_ARG ( D3DTOP,ADDSIGNED );
|
|
SWITCH_ARG ( D3DTOP,ADDSIGNED2X );
|
|
SWITCH_ARG ( D3DTOP,SUBTRACT );
|
|
SWITCH_ARG ( D3DTOP,ADDSMOOTH );
|
|
SWITCH_ARG ( D3DTOP,BLENDDIFFUSEALPHA );
|
|
SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHA );
|
|
SWITCH_ARG ( D3DTOP,BLENDFACTORALPHA );
|
|
SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHAPM );
|
|
SWITCH_ARG ( D3DTOP,BLENDCURRENTALPHA );
|
|
SWITCH_ARG ( D3DTOP,PREMODULATE );
|
|
SWITCH_ARG ( D3DTOP,MODULATEALPHA_ADDCOLOR );
|
|
SWITCH_ARG ( D3DTOP,MODULATECOLOR_ADDALPHA );
|
|
SWITCH_ARG ( D3DTOP,MODULATEINVALPHA_ADDCOLOR );
|
|
SWITCH_ARG ( D3DTOP,MODULATEINVCOLOR_ADDALPHA );
|
|
SWITCH_ARG ( D3DTOP,BUMPENVMAP );
|
|
SWITCH_ARG ( D3DTOP,BUMPENVMAPLUMINANCE );
|
|
SWITCH_ARG ( D3DTOP,DOTPRODUCT3 );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
pszOp = pszTemp;
|
|
|
|
switch ( TSSTATESELECT ( i, D3DTSS_COLORARG1 ) )
|
|
{
|
|
SWITCH_ARG ( D3DTA,DIFFUSE );
|
|
SWITCH_ARG ( D3DTA,CURRENT );
|
|
SWITCH_ARG ( D3DTA,TEXTURE );
|
|
SWITCH_ARG ( D3DTA,TFACTOR );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_COLORARG1 ) & D3DTA_ALPHAREPLICATE ) != 0 )
|
|
{
|
|
pszTempPost = ".A";
|
|
}
|
|
else
|
|
{
|
|
pszTempPost = ".C";
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_COLORARG1 ) & D3DTA_COMPLEMENT ) != 0 )
|
|
{
|
|
pszTempPre = "1-";
|
|
}
|
|
else
|
|
{
|
|
pszTempPre = "";
|
|
}
|
|
pszArg1Pre = pszTempPre;
|
|
pszArg1Post = pszTempPost;
|
|
pszArg1 = pszTemp;
|
|
|
|
|
|
switch ( TSSTATESELECT ( i, D3DTSS_COLORARG2 ) )
|
|
{
|
|
SWITCH_ARG ( D3DTA,DIFFUSE );
|
|
SWITCH_ARG ( D3DTA,CURRENT );
|
|
SWITCH_ARG ( D3DTA,TEXTURE );
|
|
SWITCH_ARG ( D3DTA,TFACTOR );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_COLORARG2 ) & D3DTA_ALPHAREPLICATE ) != 0 )
|
|
{
|
|
pszTempPost = ".A";
|
|
}
|
|
else
|
|
{
|
|
pszTempPost = ".C";
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_COLORARG2 ) & D3DTA_COMPLEMENT ) != 0 )
|
|
{
|
|
pszTempPre = "1-";
|
|
}
|
|
else
|
|
{
|
|
pszTempPre = "";
|
|
}
|
|
pszArg2Pre = pszTempPre;
|
|
pszArg2Post = pszTempPost;
|
|
pszArg2 = pszTemp;
|
|
|
|
|
|
DISPDBG((iDebugNumber," C%i: %s: %s%s%s, %s%s%s",
|
|
i, pszOp, pszArg1Pre, pszArg1, pszArg1Post,
|
|
pszArg2Pre, pszArg2, pszArg2Post ));
|
|
|
|
|
|
switch ( TSSTATE ( i, D3DTSS_ALPHAOP ) )
|
|
{
|
|
SWITCH_ARG ( D3DTOP,DISABLE );
|
|
SWITCH_ARG ( D3DTOP,SELECTARG1 );
|
|
SWITCH_ARG ( D3DTOP,SELECTARG2 );
|
|
SWITCH_ARG ( D3DTOP,MODULATE );
|
|
SWITCH_ARG ( D3DTOP,MODULATE2X );
|
|
SWITCH_ARG ( D3DTOP,MODULATE4X );
|
|
SWITCH_ARG ( D3DTOP,ADD );
|
|
SWITCH_ARG ( D3DTOP,ADDSIGNED );
|
|
SWITCH_ARG ( D3DTOP,ADDSIGNED2X );
|
|
SWITCH_ARG ( D3DTOP,SUBTRACT );
|
|
SWITCH_ARG ( D3DTOP,ADDSMOOTH );
|
|
SWITCH_ARG ( D3DTOP,BLENDDIFFUSEALPHA );
|
|
SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHA );
|
|
SWITCH_ARG ( D3DTOP,BLENDFACTORALPHA );
|
|
SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHAPM );
|
|
SWITCH_ARG ( D3DTOP,BLENDCURRENTALPHA );
|
|
SWITCH_ARG ( D3DTOP,PREMODULATE );
|
|
SWITCH_ARG ( D3DTOP,MODULATEALPHA_ADDCOLOR );
|
|
SWITCH_ARG ( D3DTOP,MODULATECOLOR_ADDALPHA );
|
|
SWITCH_ARG ( D3DTOP,MODULATEINVALPHA_ADDCOLOR );
|
|
SWITCH_ARG ( D3DTOP,MODULATEINVCOLOR_ADDALPHA );
|
|
SWITCH_ARG ( D3DTOP,BUMPENVMAP );
|
|
SWITCH_ARG ( D3DTOP,BUMPENVMAPLUMINANCE );
|
|
SWITCH_ARG ( D3DTOP,DOTPRODUCT3 );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
pszOp = pszTemp;
|
|
|
|
|
|
switch ( TSSTATESELECT ( i, D3DTSS_ALPHAARG1 ) )
|
|
{
|
|
SWITCH_ARG ( D3DTA,DIFFUSE );
|
|
SWITCH_ARG ( D3DTA,CURRENT );
|
|
SWITCH_ARG ( D3DTA,TEXTURE );
|
|
SWITCH_ARG ( D3DTA,TFACTOR );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_ALPHAARG1 ) & D3DTA_ALPHAREPLICATE ) != 0 )
|
|
{
|
|
// Alpharep doesn't mean much in the alpha channel.
|
|
pszTempPost = ".AR???";
|
|
}
|
|
else
|
|
{
|
|
pszTempPost = ".A";
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_ALPHAARG1 ) & D3DTA_COMPLEMENT ) != 0 )
|
|
{
|
|
pszTempPre = "1-";
|
|
}
|
|
else
|
|
{
|
|
pszTempPre = "";
|
|
}
|
|
pszArg1Pre = pszTempPre;
|
|
pszArg1Post = pszTempPost;
|
|
pszArg1 = pszTemp;
|
|
|
|
|
|
switch ( TSSTATESELECT ( i, D3DTSS_ALPHAARG2 ) )
|
|
{
|
|
SWITCH_ARG ( D3DTA,DIFFUSE );
|
|
SWITCH_ARG ( D3DTA,CURRENT );
|
|
SWITCH_ARG ( D3DTA,TEXTURE );
|
|
SWITCH_ARG ( D3DTA,TFACTOR );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_ALPHAARG2 ) & D3DTA_ALPHAREPLICATE ) != 0 )
|
|
{
|
|
pszTempPost = ".AR???";
|
|
}
|
|
else
|
|
{
|
|
pszTempPost = ".A";
|
|
}
|
|
if ( ( TSSTATE ( i, D3DTSS_ALPHAARG2 ) & D3DTA_COMPLEMENT ) != 0 )
|
|
{
|
|
pszTempPre = "1-";
|
|
}
|
|
else
|
|
{
|
|
pszTempPre = "";
|
|
}
|
|
pszArg2Pre = pszTempPre;
|
|
pszArg2Post = pszTempPost;
|
|
pszArg2 = pszTemp;
|
|
|
|
DISPDBG((iDebugNumber," A%i: %s: %s%s%s, %s%s%s",
|
|
i, pszOp, pszArg1Pre, pszArg1, pszArg1Post,
|
|
pszArg2Pre, pszArg2, pszArg2Post ));
|
|
|
|
|
|
if ( TSSTATE ( i, D3DTSS_TEXTUREMAP ) != 0 )
|
|
{
|
|
char szTemp[4];
|
|
// Setup texture 0.
|
|
pTexture = GetSurfaceFromHandle(pContext,
|
|
TSSTATE(i, D3DTSS_TEXTUREMAP));
|
|
if ( pTexture == NULL )
|
|
{
|
|
DISPDBG((iDebugNumber," Tex%i: 0x%x, TCI: %i, INVALID TEXTURE",
|
|
i, TSSTATE ( i, D3DTSS_TEXTUREMAP ),
|
|
TSSTATE ( i, D3DTSS_TEXCOORDINDEX ) ));
|
|
}
|
|
else
|
|
{
|
|
pFormatSurface = pTexture->pFormatSurface;
|
|
ASSERTDD ( pFormatSurface != NULL,
|
|
"** _D3DDisplayWholeTSSPipe: "
|
|
"Surface had NULL format!" );
|
|
|
|
// Find the filtering mode.
|
|
szTemp[3] = '\0';
|
|
switch ( TSSTATE ( i, D3DTSS_MINFILTER ) )
|
|
{
|
|
case D3DTFN_POINT:
|
|
szTemp[0] = 'P';
|
|
break;
|
|
case D3DTFN_LINEAR:
|
|
szTemp[0] = 'L';
|
|
break;
|
|
case D3DTFN_ANISOTROPIC:
|
|
szTemp[0] = 'A';
|
|
break;
|
|
default:
|
|
szTemp[0] = '?';
|
|
break;
|
|
}
|
|
switch ( TSSTATE ( i, D3DTSS_MIPFILTER ) )
|
|
{
|
|
case D3DTFP_NONE:
|
|
szTemp[1] = 'x';
|
|
break;
|
|
case D3DTFP_POINT:
|
|
szTemp[1] = 'P';
|
|
break;
|
|
case D3DTFP_LINEAR:
|
|
szTemp[1] = 'L';
|
|
break;
|
|
default:
|
|
szTemp[1] = '?';
|
|
break;
|
|
}
|
|
switch ( TSSTATE ( i, D3DTSS_MAGFILTER ) )
|
|
{
|
|
case D3DTFG_POINT:
|
|
szTemp[2] = 'P';
|
|
break;
|
|
case D3DTFG_LINEAR:
|
|
szTemp[2] = 'L';
|
|
break;
|
|
case D3DTFG_FLATCUBIC:
|
|
szTemp[2] = 'F';
|
|
break;
|
|
case D3DTFG_GAUSSIANCUBIC:
|
|
szTemp[2] = 'G';
|
|
break;
|
|
case D3DTFG_ANISOTROPIC:
|
|
szTemp[2] = 'A';
|
|
break;
|
|
default:
|
|
szTemp[2] = '?';
|
|
break;
|
|
}
|
|
|
|
DISPDBG((iDebugNumber," Tex%i: 0x%x, TCI: %i, %s:%dx%d %s",
|
|
i, TSSTATE ( i, D3DTSS_TEXTUREMAP ),
|
|
TSSTATE ( i, D3DTSS_TEXCOORDINDEX ),
|
|
pFormatSurface->pszStringFormat,
|
|
pTexture->wWidth,
|
|
pTexture->wHeight, szTemp ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((iDebugNumber," Tex%i: NULL, TCI: %i",
|
|
i, TSSTATE ( i, D3DTSS_TEXCOORDINDEX ) ));
|
|
}
|
|
|
|
|
|
i++;
|
|
}
|
|
|
|
// Alpha-test.
|
|
if ( pContext->RenderStates[D3DRENDERSTATE_ALPHATESTENABLE] != 0 )
|
|
{
|
|
switch ( pContext->RenderStates[D3DRENDERSTATE_ALPHAFUNC] )
|
|
{
|
|
SWITCH_ARG ( D3DCMP,NEVER );
|
|
SWITCH_ARG ( D3DCMP,LESS );
|
|
SWITCH_ARG ( D3DCMP,EQUAL );
|
|
SWITCH_ARG ( D3DCMP,LESSEQUAL );
|
|
SWITCH_ARG ( D3DCMP,GREATER );
|
|
SWITCH_ARG ( D3DCMP,NOTEQUAL );
|
|
SWITCH_ARG ( D3DCMP,GREATEREQUAL );
|
|
SWITCH_ARG ( D3DCMP,ALWAYS );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
DISPDBG((iDebugNumber,"Alpha-test: %s:0x%x.",
|
|
pszTemp, pContext->RenderStates[D3DRENDERSTATE_ALPHAREF] ));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((iDebugNumber,"No alpha-test."));
|
|
}
|
|
|
|
|
|
// Alpha-blend.
|
|
if ( pContext->RenderStates[D3DRENDERSTATE_BLENDENABLE] != 0 )
|
|
{
|
|
switch ( pContext->RenderStates[D3DRENDERSTATE_SRCBLEND] )
|
|
{
|
|
SWITCH_ARG ( D3DBLEND,ZERO );
|
|
SWITCH_ARG ( D3DBLEND,ONE );
|
|
SWITCH_ARG ( D3DBLEND,SRCCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,INVSRCCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,SRCALPHA );
|
|
SWITCH_ARG ( D3DBLEND,INVSRCALPHA );
|
|
SWITCH_ARG ( D3DBLEND,DESTALPHA );
|
|
SWITCH_ARG ( D3DBLEND,INVDESTALPHA );
|
|
SWITCH_ARG ( D3DBLEND,DESTCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,INVDESTCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,SRCALPHASAT );
|
|
SWITCH_ARG ( D3DBLEND,BOTHSRCALPHA );
|
|
SWITCH_ARG ( D3DBLEND,BOTHINVSRCALPHA );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
pszSrc = pszTemp;
|
|
|
|
switch ( pContext->RenderStates[D3DRENDERSTATE_DESTBLEND] )
|
|
{
|
|
SWITCH_ARG ( D3DBLEND,ZERO );
|
|
SWITCH_ARG ( D3DBLEND,ONE );
|
|
SWITCH_ARG ( D3DBLEND,SRCCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,INVSRCCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,SRCALPHA );
|
|
SWITCH_ARG ( D3DBLEND,INVSRCALPHA );
|
|
SWITCH_ARG ( D3DBLEND,DESTALPHA );
|
|
SWITCH_ARG ( D3DBLEND,INVDESTALPHA );
|
|
SWITCH_ARG ( D3DBLEND,DESTCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,INVDESTCOLOR );
|
|
SWITCH_ARG ( D3DBLEND,SRCALPHASAT );
|
|
SWITCH_ARG ( D3DBLEND,BOTHSRCALPHA );
|
|
SWITCH_ARG ( D3DBLEND,BOTHINVSRCALPHA );
|
|
default:
|
|
pszTemp = "Unknown";
|
|
break;
|
|
}
|
|
pszDest = pszTemp;
|
|
DISPDBG((iDebugNumber,"Blend %s:%s", pszSrc, pszDest));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((iDebugNumber,"No alpha-blend."));
|
|
}
|
|
|
|
#undef SWITCH_ARG
|
|
|
|
#endif //DBG
|
|
} // _D3DDisplayWholeTSSPipe
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// __TXT_TranslateToChipBlendMode
|
|
//
|
|
// Translates the blend mode from D3D into what the chip understands
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
__TXT_TranslateToChipBlendMode(
|
|
P3_D3DCONTEXT *pContext,
|
|
TexStageState* pState,
|
|
P3_SOFTWARECOPY* pSoftP3RX,
|
|
int iTSStage,
|
|
int iChipStageNo )
|
|
{
|
|
struct TextureCompositeRGBAMode* pColorMode;
|
|
struct TextureCompositeRGBAMode* pAlphaMode;
|
|
struct TextureApplicationMode* pTAMode;
|
|
|
|
switch(iChipStageNo)
|
|
{
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Invalid texture stage!"));
|
|
// Fall through and treat as #0 in order not to AV anything
|
|
case 0:
|
|
pColorMode = &pSoftP3RX->P3RXTextureCompositeColorMode0;
|
|
pAlphaMode = &pSoftP3RX->P3RXTextureCompositeAlphaMode0;
|
|
pTAMode = NULL;
|
|
break;
|
|
case 1:
|
|
pColorMode = &pSoftP3RX->P3RXTextureCompositeColorMode1;
|
|
pAlphaMode = &pSoftP3RX->P3RXTextureCompositeAlphaMode1;
|
|
pTAMode = NULL;
|
|
break;
|
|
case 2:
|
|
pColorMode = NULL;
|
|
pAlphaMode = NULL;
|
|
pTAMode = &pSoftP3RX->P3RXTextureApplicationMode;
|
|
break;
|
|
|
|
}
|
|
|
|
DISPDBG((DBGLVL,"*** In __TXT_TranslateToChipBlendMode: "
|
|
"Chip Stage %d, D3D TSS Stage %d",
|
|
iChipStageNo, iTSStage ));
|
|
|
|
// Setup the arguments
|
|
if ( ( iChipStageNo == 0 ) || ( iChipStageNo == 1 ) )
|
|
{
|
|
// Texture composite unit.
|
|
DISPDBG((DBGLVL,"TexComp%d:", iChipStageNo ));
|
|
DISPDBG((DBGLVL,"Arg1:" ));
|
|
|
|
SETARG(pContext,
|
|
pColorMode,
|
|
pState->m_dwVal[D3DTSS_COLORARG1],
|
|
1,
|
|
IS_COLOR_ARG,
|
|
iTSStage,
|
|
iChipStageNo);
|
|
|
|
SETARG(pContext,
|
|
pAlphaMode,
|
|
pState->m_dwVal[D3DTSS_ALPHAARG1],
|
|
1,
|
|
IS_ALPHA_ARG,
|
|
iTSStage,
|
|
iChipStageNo);
|
|
|
|
DISPDBG((DBGLVL,"Arg2:" ));
|
|
|
|
SETARG(pContext,
|
|
pColorMode,
|
|
pState->m_dwVal[D3DTSS_COLORARG2],
|
|
2,
|
|
IS_COLOR_ARG,
|
|
iTSStage,
|
|
iChipStageNo);
|
|
|
|
SETARG(pContext,
|
|
pAlphaMode,
|
|
pState->m_dwVal[D3DTSS_ALPHAARG2],
|
|
2,
|
|
IS_ALPHA_ARG,
|
|
iTSStage,
|
|
iChipStageNo);
|
|
|
|
DISPDBG((DBGLVL,"Op:" ));
|
|
SETOP(pContext,
|
|
pColorMode,
|
|
pState->m_dwVal[D3DTSS_COLOROP],
|
|
iTSStage,
|
|
iChipStageNo,
|
|
IS_COLOR_ARG);
|
|
|
|
SETOP(pContext,
|
|
pAlphaMode,
|
|
pState->m_dwVal[D3DTSS_ALPHAOP],
|
|
iTSStage,
|
|
iChipStageNo,
|
|
IS_ALPHA_ARG);
|
|
}
|
|
else if ( iChipStageNo == 2 )
|
|
{
|
|
DISPDBG((DBGLVL,"TexApp:" ));
|
|
DISPDBG((DBGLVL,"Arg1:" ));
|
|
|
|
SETTAARG_COLOR(pContext,
|
|
pTAMode,
|
|
pState->m_dwVal[D3DTSS_COLORARG1],
|
|
1 );
|
|
|
|
if ( ( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_DISABLE ) &&
|
|
( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_SELECTARG2 ) )
|
|
{
|
|
SETTAARG_ALPHA(pContext,
|
|
pTAMode,
|
|
pState->m_dwVal[D3DTSS_ALPHAARG1], 1
|
|
);
|
|
}
|
|
|
|
DISPDBG((DBGLVL,"Arg2:" ));
|
|
SETTAARG_COLOR(pContext,
|
|
pTAMode,
|
|
pState->m_dwVal[D3DTSS_COLORARG2],
|
|
2 );
|
|
|
|
if ( ( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_DISABLE ) &&
|
|
( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_SELECTARG1 ) )
|
|
{
|
|
SETTAARG_ALPHA(pContext,
|
|
pTAMode,
|
|
pState->m_dwVal[D3DTSS_ALPHAARG2],
|
|
2);
|
|
}
|
|
|
|
DISPDBG((DBGLVL,"Op:" ));
|
|
SETTAOP(pContext,
|
|
pTAMode,
|
|
pState->m_dwVal[D3DTSS_COLOROP],
|
|
IS_COLOR_ARG,
|
|
iTSStage,
|
|
iChipStageNo);
|
|
|
|
SETTAOP(pContext,
|
|
pTAMode,
|
|
pState->m_dwVal[D3DTSS_ALPHAOP],
|
|
IS_ALPHA_ARG,
|
|
iTSStage,
|
|
iChipStageNo);
|
|
}
|
|
else
|
|
{
|
|
DISPDBG(( ERRLVL,"** __TXT_TranslateToChipBlendMode: "
|
|
"iChipStage must be 0 to 2" ));
|
|
}
|
|
} // __TXT_TranslateToChipBlendMode
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// __TXT_ValidateTextureUnitStage
|
|
//
|
|
// Validate the texture which we're trying to set up in stage iChipStage of
|
|
// the hardware, iTSStage of the D3D TSS.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL
|
|
__TXT_ValidateTextureUnitStage(
|
|
P3_D3DCONTEXT* pContext,
|
|
int iChipStage,
|
|
int iTSStage,
|
|
P3_SURF_INTERNAL* pTexture)
|
|
{
|
|
DWORD dwTexHandle =
|
|
pContext->TextureStageState[iTSStage].m_dwVal[D3DTSS_TEXTUREMAP];
|
|
|
|
if( CHECK_SURF_INTERNAL_AND_DDSURFACE_VALIDITY(pTexture) &&
|
|
(pTexture->Location != SystemMemory) &&
|
|
(dwTexHandle != 0) )
|
|
{
|
|
// Texture is valid. Mark pCurrentTexturep[iChipStage] to point
|
|
// to its P3_SURF_INTERNAL structure.
|
|
pContext->pCurrentTexture[iChipStage] = pTexture;
|
|
|
|
DISPDBG((DBGLVL, "__TXT_ValidateTextureUnitStage: valid texture %x "
|
|
"(handle %d) for iChipStage= %d iTSStage= %d",
|
|
pTexture, dwTexHandle, iChipStage, iTSStage));
|
|
}
|
|
else
|
|
{
|
|
// Set texture as invalid & force texturing off
|
|
pContext->bTextureValid = FALSE;
|
|
pContext->pCurrentTexture[iChipStage] = NULL;
|
|
pContext->dwDirtyFlags |= CONTEXT_DIRTY_TEXTURE;
|
|
|
|
// Setup error if we're asked to validate the TSS setup
|
|
SET_BLEND_ERROR ( pContext, BSF_INVALID_TEXTURE );
|
|
|
|
DISPDBG((WRNLVL, "__TXT_ValidateTextureUnitStage: INVALID texture %x "
|
|
"(handle %d) for iChipStage= %d iTSStage= %d "
|
|
"Location=%d",
|
|
pTexture, dwTexHandle, iChipStage, iTSStage,
|
|
(pTexture !=NULL)?pTexture->Location:0));
|
|
}
|
|
|
|
return ( (BOOL)pContext->bTextureValid );
|
|
|
|
} // __TXT_ValidateTextureUnitStage
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// __TXT_ConsiderSrcChromaKey
|
|
//
|
|
// Setup chromakeying for a certain texture bound to a certain stage.
|
|
// Note - "stage" is the chip stage, not the D3D stage.
|
|
//-----------------------------------------------------------------------------
|
|
static void
|
|
__TXT_ConsiderSrcChromaKey(
|
|
P3_D3DCONTEXT *pContext,
|
|
P3_SURF_INTERNAL* pTexture,
|
|
int stage )
|
|
{
|
|
P3_THUNKEDDATA * pThisDisplay = pContext->pThisDisplay;
|
|
P3_SOFTWARECOPY* pSoftP3RX = &pContext->SoftCopyGlint;
|
|
P3_DMA_DEFS();
|
|
|
|
if ((pTexture->dwFlagsInt & DDRAWISURF_HASCKEYSRCBLT) &&
|
|
pContext->RenderStates[D3DRENDERSTATE_COLORKEYENABLE])
|
|
{
|
|
DWORD LowerBound = 0x00000000;
|
|
DWORD UpperBound = 0xFFFFFFFF;
|
|
DWORD* pPalEntries = NULL;
|
|
DWORD dwPalFlags = 0;
|
|
|
|
DISPDBG((DBGLVL," Can Chroma Key texture stage %d", stage));
|
|
|
|
pContext->bCanChromaKey = TRUE;
|
|
|
|
#if DX7_PALETTETEXTURE
|
|
// Get the palette entries
|
|
if (pTexture->pixFmt.dwFlags & DDPF_PALETTEINDEXED8)
|
|
{
|
|
D3DHAL_DP2UPDATEPALETTE *pPalette = NULL;
|
|
|
|
pPalette = GetPaletteFromHandle(pContext,
|
|
pTexture->dwPaletteHandle);
|
|
if (pPalette)
|
|
{
|
|
pPalEntries = (LPDWORD)(pPalette + 1);
|
|
}
|
|
else
|
|
{
|
|
SET_BLEND_ERROR(pContext, BSF_INVALID_TEXTURE);
|
|
}
|
|
|
|
dwPalFlags = pTexture->dwPaletteFlags;
|
|
}
|
|
#endif
|
|
|
|
// Get the correct chroma value for the texture map to send to the chip.
|
|
Get8888ScaledChroma(pThisDisplay,
|
|
pTexture->dwFlagsInt,
|
|
&pTexture->pixFmt,
|
|
pTexture->dwCKLow,
|
|
pTexture->dwCKHigh,
|
|
&LowerBound,
|
|
&UpperBound,
|
|
pPalEntries,
|
|
dwPalFlags & DDRAWIPAL_ALPHA,
|
|
FALSE);
|
|
|
|
P3_DMA_GET_BUFFER_ENTRIES( 8);
|
|
|
|
// Send the upper and lower bounds for the alpha-map filtering
|
|
if( stage == 0 )
|
|
{
|
|
SEND_P3_DATA(TextureChromaLower0, LowerBound );
|
|
SEND_P3_DATA(TextureChromaUpper0, UpperBound );
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable0 =
|
|
__PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapSense0 =
|
|
P3RX_ALPHAMAPSENSE_INRANGE;
|
|
}
|
|
else
|
|
{
|
|
ASSERTDD ( stage == 1,
|
|
"** __TXT_ConsiderSrcChromaKey: stage must be 0 or 1" );
|
|
}
|
|
|
|
// If we are mipmapping, we need to set up texture1's chromakey as well.
|
|
// If not, then this will be overridden when this gets called for tex1.
|
|
SEND_P3_DATA(TextureChromaLower1, LowerBound );
|
|
SEND_P3_DATA(TextureChromaUpper1, UpperBound );
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable1 = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapSense1 =
|
|
P3RX_ALPHAMAPSENSE_INRANGE;
|
|
|
|
P3_DMA_COMMIT_BUFFER();
|
|
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFiltering = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((DBGLVL," Can't Chroma Key texture stage %d", stage));
|
|
|
|
if( stage == 0 )
|
|
{
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable0 =
|
|
__PERMEDIA_DISABLE;
|
|
}
|
|
else
|
|
{
|
|
ASSERTDD ( stage == 1,
|
|
"** __TXT_ConsiderSrcChromaKey: stage must be 0 or 1" );
|
|
}
|
|
|
|
// If we are mipmapping, we need to set up texture1's chromakey (or
|
|
// lack of it) as well. If not, then this will be overridden when
|
|
// this gets called for tex1.
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFiltering = __PERMEDIA_DISABLE;
|
|
}
|
|
} // __TXT_ConsiderSrcChromaKey
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// __TXT_SetupTexture
|
|
//
|
|
// This is the new all-singing all-dancing texture setup code.
|
|
// Return is TRUE if setup succeeded, FALSE if it failed (for ValidateDevice)
|
|
// This sets up either texture 0 or texture 1, taking its wrapping, etc,
|
|
// info from iTSStage.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL __TXT_SetupTexture (
|
|
P3_THUNKEDDATA * pThisDisplay,
|
|
int iTexNo,
|
|
int iTSStage,
|
|
P3_D3DCONTEXT* pContext,
|
|
P3_SURF_INTERNAL* pTexture,
|
|
P3_SOFTWARECOPY* pSoftP3RX,
|
|
BOOL bBothTexturesValid,
|
|
P3_MIP_BASES *pMipBases)
|
|
{
|
|
P3_SURF_FORMAT* pFormatSurface;
|
|
int iT0MaxLevel, iT1MaxLevel;
|
|
|
|
P3_DMA_DEFS();
|
|
|
|
ASSERTDD ( ( iTexNo >= 0 ) && ( iTexNo <= 1 ),
|
|
"**__TXT_SetupTexture: we only have two texture units!" );
|
|
|
|
if ( pTexture != NULL )
|
|
{
|
|
pFormatSurface = pTexture->pFormatSurface;
|
|
}
|
|
else
|
|
{
|
|
// Suceeded, but should never have got here!
|
|
DISPDBG((ERRLVL,"**__TXT_SetupTexture: should never "
|
|
"be called with handle of NULL"));
|
|
return ( TRUE );
|
|
}
|
|
|
|
P3_DMA_GET_BUFFER();
|
|
P3_ENSURE_DX_SPACE(32);
|
|
WAIT_FIFO(32);
|
|
|
|
// Set up the texture-relevant things.
|
|
|
|
switch ( iTexNo )
|
|
{
|
|
case 0:
|
|
{
|
|
// Set both bits in case we are mipmapping
|
|
|
|
pSoftP3RX->P3RXTextureFilterMode.ForceAlphaToOne0 =
|
|
pFormatSurface->bAlpha ?
|
|
__PERMEDIA_DISABLE :
|
|
__PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureFilterMode.ForceAlphaToOne1 =
|
|
pFormatSurface->bAlpha ?
|
|
__PERMEDIA_DISABLE :
|
|
__PERMEDIA_ENABLE;
|
|
|
|
// D3D UV Wrapping
|
|
if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage]
|
|
& D3DWRAP_U)
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapS = 1;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapS = 0;
|
|
}
|
|
|
|
if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage]
|
|
& D3DWRAP_V)
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapT = 1;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapT = 0;
|
|
}
|
|
|
|
// U Wrapping
|
|
switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSU ))
|
|
{
|
|
case D3DTADDRESS_CLAMP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS =
|
|
__GLINT_TEXADDRESS_WRAP_CLAMP;
|
|
pSoftP3RX->P3RXTextureIndexMode0.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
|
|
break;
|
|
case D3DTADDRESS_WRAP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS =
|
|
__GLINT_TEXADDRESS_WRAP_REPEAT;
|
|
pSoftP3RX->P3RXTextureIndexMode0.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_REPEAT;
|
|
break;
|
|
case D3DTADDRESS_MIRROR:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS =
|
|
__GLINT_TEXADDRESS_WRAP_MIRROR;
|
|
pSoftP3RX->P3RXTextureIndexMode0.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_MIRROR;
|
|
break;
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSU!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
|
|
break;
|
|
}
|
|
|
|
// V Wrapping
|
|
switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSV ))
|
|
{
|
|
case D3DTADDRESS_CLAMP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapT =
|
|
__GLINT_TEXADDRESS_WRAP_CLAMP;
|
|
pSoftP3RX->P3RXTextureIndexMode0.WrapV =
|
|
P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
|
|
break;
|
|
case D3DTADDRESS_WRAP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapT =
|
|
__GLINT_TEXADDRESS_WRAP_REPEAT;
|
|
pSoftP3RX->P3RXTextureIndexMode0.WrapV =
|
|
P3RX_TEXINDEXMODE_WRAP_REPEAT;
|
|
break;
|
|
case D3DTADDRESS_MIRROR:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapT =
|
|
__GLINT_TEXADDRESS_WRAP_MIRROR;
|
|
pSoftP3RX->P3RXTextureIndexMode0.WrapV =
|
|
P3RX_TEXINDEXMODE_WRAP_MIRROR;
|
|
break;
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSV!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
|
|
break;
|
|
}
|
|
|
|
#if DX8_3DTEXTURES
|
|
if (pTexture->b3DTexture)
|
|
{
|
|
// W Wrapping
|
|
switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSW ))
|
|
{
|
|
case D3DTADDRESS_CLAMP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
|
|
__GLINT_TEXADDRESS_WRAP_CLAMP;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
|
|
break;
|
|
|
|
case D3DTADDRESS_WRAP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
|
|
__GLINT_TEXADDRESS_WRAP_REPEAT;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_REPEAT;
|
|
break;
|
|
|
|
case D3DTADDRESS_MIRROR:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
|
|
__GLINT_TEXADDRESS_WRAP_MIRROR;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_MIRROR;
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSW!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
|
|
break;
|
|
}
|
|
}
|
|
#endif // DX8_3DTEXTURES
|
|
|
|
if(( TSSTATE( iTSStage, D3DTSS_ADDRESSU ) == D3DTADDRESS_CLAMP ) ||
|
|
( TSSTATE( iTSStage, D3DTSS_ADDRESSV ) == D3DTADDRESS_CLAMP ))
|
|
{
|
|
if( (TSSTATE( iTSStage, D3DTSS_ADDRESSU ) != D3DTADDRESS_CLAMP) ||
|
|
(TSSTATE( iTSStage, D3DTSS_ADDRESSV ) != D3DTADDRESS_CLAMP))
|
|
{
|
|
DISPDBG((ERRLVL,"Warning: One texture coord clamped, but not "
|
|
"the other - can't appply TextureShift"));
|
|
}
|
|
|
|
pSoftP3RX->P4DeltaFormatControl.TextureShift =
|
|
__PERMEDIA_DISABLE;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.TextureShift =
|
|
__PERMEDIA_ENABLE;
|
|
}
|
|
|
|
ASSERTDD ( pFormatSurface != NULL,
|
|
"** SetupTextureUnitStage: logic error: "
|
|
"pFormatSurace is NULL" );
|
|
switch (pFormatSurface->DeviceFormat)
|
|
{
|
|
case SURF_CI8:
|
|
pSoftP3RX->P3RXTextureReadMode0.TextureType =
|
|
P3RX_TEXREADMODE_TEXTURETYPE_8BITINDEXED;
|
|
break;
|
|
|
|
case SURF_YUV422:
|
|
pSoftP3RX->P3RXTextureReadMode0.TextureType =
|
|
P3RX_TEXREADMODE_TEXTURETYPE_422_YVYU;
|
|
break;
|
|
|
|
default:
|
|
pSoftP3RX->P3RXTextureReadMode0.TextureType =
|
|
P3RX_TEXREADMODE_TEXTURETYPE_NORMAL;
|
|
break;
|
|
}
|
|
|
|
// MAG Filter
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MAGFILTER ))
|
|
{
|
|
case D3DTFG_POINT:
|
|
pSoftP3RX->P3RXTextureIndexMode0.MagnificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEAREST;
|
|
break;
|
|
|
|
case D3DTFG_LINEAR:
|
|
pSoftP3RX->P3RXTextureIndexMode0.MagnificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEAR;
|
|
break;
|
|
|
|
case D3DTFG_FLATCUBIC:
|
|
case D3DTFG_GAUSSIANCUBIC:
|
|
case D3DTFG_ANISOTROPIC:
|
|
DISPDBG((ERRLVL,"ERROR: Unsupported MAGFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown MAGFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
|
|
break;
|
|
}
|
|
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
|
|
{
|
|
case D3DTFN_POINT:
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEAREST;
|
|
break;
|
|
|
|
case D3DTFN_LINEAR:
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEAR;
|
|
break;
|
|
|
|
case D3DTFN_ANISOTROPIC:
|
|
DISPDBG((ERRLVL,"ERROR: Unsupported MINFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown MINFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
|
|
break;
|
|
}
|
|
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MIPFILTER ))
|
|
{
|
|
case D3DTFP_NONE:
|
|
// No need to set the minification filter, it was done above
|
|
break;
|
|
|
|
case D3DTFP_POINT:
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
|
|
{
|
|
case D3DTFN_POINT:
|
|
// Point Min, Point Mip
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEARMIPNEAREST;
|
|
break;
|
|
case D3DTFN_LINEAR:
|
|
// Linear Min, Point Mip
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEARMIPNEAREST;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case D3DTFP_LINEAR:
|
|
if( bBothTexturesValid )
|
|
{
|
|
// We can only do per-poly mipmapping while
|
|
// multi-texturing, so don't enable inter-map filtering.
|
|
|
|
// Non-fatal error - drop back to nearest
|
|
// mipmap filtering.
|
|
SET_BLEND_ERROR ( pContext, BS_INVALID_FILTER );
|
|
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
|
|
{
|
|
case D3DTFN_POINT:
|
|
// Point Min, Point Mip
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEARMIPNEAREST;
|
|
break;
|
|
case D3DTFN_LINEAR:
|
|
// Linear Min, Point Mip
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEARMIPNEAREST;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Single texture - do inter-map filtering
|
|
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
|
|
{
|
|
case D3DTFN_POINT:
|
|
// Point Min, Linear Mip
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEARMIPLINEAR;
|
|
break;
|
|
case D3DTFN_LINEAR:
|
|
// Linear Min, Linear Mip
|
|
pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEARMIPLINEAR;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown MIPFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
|
|
break;
|
|
}
|
|
|
|
// MipMapping
|
|
if( (TSSTATE ( iTSStage, D3DTSS_MIPFILTER ) != D3DTFP_NONE) &&
|
|
(pTexture->bMipMap))
|
|
{
|
|
int iLOD;
|
|
INT iTexLOD;
|
|
|
|
DISPDBG(( DBGLVL, "Multiple texture levels" ));
|
|
|
|
// Load the mipmap levels for texture 0
|
|
// Mip level from pMipBases->dwTex0ActMaxLevel to
|
|
// pTexture->iMipLevels will be mapped to base address slot
|
|
// from pMipBases->dwTex0Mipbase to dwTex0MipMax
|
|
ASSERTDD ( pMipBases->dwTex0MipBase == 0,
|
|
"** __TXT_SetupTexture: "
|
|
"Texture 0 mipmap base is not 0" );
|
|
|
|
iLOD = pMipBases->dwTex0MipBase;
|
|
iTexLOD = pMipBases->dwTex0ActMaxLevel;
|
|
iT0MaxLevel = iTexLOD;
|
|
|
|
while(( iTexLOD < pTexture->iMipLevels ) &&
|
|
( iLOD <= (int)pMipBases->dwTex0MipMax ))
|
|
{
|
|
DISPDBG((DBGLVL, " Setting Texture Base Address %d to 0x%x",
|
|
iLOD, pTexture->MipLevels[iLOD].dwOffsetFromMemoryBase));
|
|
|
|
pSoftP3RX->P3RXTextureMapWidth[iLOD] =
|
|
pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
|
|
|
|
#if DX7_TEXMANAGEMENT
|
|
// If this is a driver managed texture surface, we need
|
|
// to use our privately allocated mem ptr
|
|
if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
(DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
|
|
iLOD);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
|
|
iLOD);
|
|
}
|
|
|
|
iLOD++;
|
|
iTexLOD++;
|
|
}
|
|
|
|
// If both textures are enabled we can't do per-pixel
|
|
// mipmapping because that uses both sets of texcoord
|
|
// DDAs to generate the LOD level. So we must do per-poly
|
|
// mipmapping. Per-poly mipmapping can only be done in
|
|
// hardware on P4 - we use a Delta renderer on P3 when
|
|
// mipmapping with both textures enabled.
|
|
|
|
if( bBothTexturesValid )
|
|
{
|
|
DISPDBG(( DBGLVL, "Both textures valid" ));
|
|
|
|
// Do per-poly mipmapping in the P4 DeltaFormat unit
|
|
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableLOD =
|
|
__PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableDY =
|
|
__PERMEDIA_DISABLE;
|
|
pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
|
|
__PERMEDIA_ENABLE;
|
|
|
|
{
|
|
DWORD d;
|
|
|
|
*(float *)&d =
|
|
pContext->MipMapLODBias[TEXSTAGE_0] *
|
|
pTexture->dwPixelPitch *
|
|
pTexture->wHeight;
|
|
|
|
SEND_P3_DATA(TextureLODScale, d);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DISPDBG(( DBGLVL, "Single texture only" ));
|
|
|
|
// Do per-pixel mipmapping
|
|
|
|
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableLOD =
|
|
__PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableDY =
|
|
__PERMEDIA_ENABLE;
|
|
pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
|
|
__PERMEDIA_DISABLE;
|
|
|
|
//@@BEGIN_DDKSPLIT
|
|
#if 0
|
|
// azn this would disable "automatic" mip mapping and we would be using the
|
|
// values supplied by writing into LOD and LOD1 (d3dprim.c) - don't forget!
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableLOD =
|
|
__PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableDY =
|
|
__PERMEDIA_DISABLE;
|
|
pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
|
|
__PERMEDIA_ENABLE;
|
|
SEND_P3_DATA(TextureLODScale, 0);
|
|
#endif
|
|
//@@END_DDKSPLIT
|
|
{
|
|
float bias;
|
|
DWORD b;
|
|
|
|
bias = pContext->TextureStageState[TEXSTAGE_0].m_fVal[D3DTSS_MIPMAPLODBIAS];
|
|
|
|
// Convert LOD bias from float to 6.8
|
|
|
|
myFtoi( &b, bias * 256.0f );
|
|
|
|
SEND_P3_DATA(TextureLODBiasS, b);
|
|
SEND_P3_DATA(TextureLODBiasT, b);
|
|
}
|
|
}
|
|
|
|
pSoftP3RX->P3RXTextureIndexMode0.MipMapEnable =
|
|
__PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
int iTexLOD;
|
|
|
|
// No mipmapping.
|
|
DISPDBG(( DBGLVL, "Single texture level" ));
|
|
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableLOD = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableDY = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
|
|
__PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode0.MipMapEnable =
|
|
__PERMEDIA_DISABLE;
|
|
|
|
ASSERTDD ( pMipBases->dwTex0MipBase == 0,
|
|
"** __TXT_SetupTexture: "
|
|
"Texture 0 mipmap base is not 0" );
|
|
|
|
// Use the maximum level indicated by D3DTSS_MAXMIPLEVEL
|
|
iTexLOD = pMipBases->dwTex0ActMaxLevel;
|
|
iT0MaxLevel = iTexLOD;
|
|
|
|
#if DX7_TEXMANAGEMENT
|
|
// If this is a driver managed texture surface, we need
|
|
// to use our privately allocated mem ptr
|
|
if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
(DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
|
|
0);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
|
|
0);
|
|
}
|
|
|
|
// No mipmapping, but could be combining the caches.
|
|
pSoftP3RX->P3RXTextureMapWidth[0] =
|
|
pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
|
|
pSoftP3RX->P3RXTextureMapWidth[1] =
|
|
pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
|
|
}
|
|
|
|
//@@BEGIN_DDKSPLIT
|
|
// There is only one TextureCoordMode, it is possible that it is
|
|
// not used at all
|
|
//@@END_DDKSPLIT
|
|
// Set maximum dimension of the texture
|
|
pSoftP3RX->P3RXTextureCoordMode.Width = pTexture->MipLevels[iT0MaxLevel].logWidth;
|
|
pSoftP3RX->P3RXTextureCoordMode.Height = pTexture->MipLevels[iT0MaxLevel].logHeight;
|
|
#if DX7_PALETTETEXTURE
|
|
// If it is a palette indexed texture, we simply follow the chain
|
|
// down from the surface to its palette and pull out the LUT values
|
|
// from the PALETTEENTRY's in the palette.
|
|
ASSERTDD ( pFormatSurface != NULL, "** SetupTextureUnitStage: logic error: pFormatSurace is NULL" );
|
|
if (pFormatSurface->DeviceFormat == SURF_CI8)
|
|
{
|
|
WAIT_FIFO(8);
|
|
|
|
pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXLUTMode.InColorOrder = __PERMEDIA_ENABLE;
|
|
SEND_P3_DATA(LUTAddress, 0);
|
|
SEND_P3_DATA(LUTTransfer, 0);
|
|
SEND_P3_DATA(LUTIndex, 0);
|
|
COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode);
|
|
|
|
// In this case simply download the 256 entries each time the
|
|
// texture handle changes.
|
|
{
|
|
DWORD dwCount1, dwCount2;
|
|
D3DHAL_DP2UPDATEPALETTE *pPalette; // associated palette
|
|
LPDWORD lpColorTable; // array of palette entries
|
|
|
|
pPalette = GetPaletteFromHandle(pContext,
|
|
pTexture->dwPaletteHandle);
|
|
if (pPalette) // If palette can be found
|
|
{
|
|
lpColorTable = (LPDWORD)(pPalette + 1);
|
|
|
|
if (pTexture->dwPaletteFlags & DDRAWIPAL_ALPHA)
|
|
{
|
|
for (dwCount1 = 0; dwCount1 < 16; dwCount1++)
|
|
{
|
|
P3_ENSURE_DX_SPACE(17);
|
|
WAIT_FIFO(17);
|
|
P3RX_HOLD_CMD(LUTData, 16);
|
|
for (dwCount2 = 0; dwCount2 < 16; dwCount2++)
|
|
{
|
|
*dmaPtr++ = *lpColorTable++;
|
|
CHECK_FIFO(1);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (dwCount1 = 0; dwCount1 < 16; dwCount1++)
|
|
{
|
|
P3_ENSURE_DX_SPACE(17);
|
|
WAIT_FIFO(17);
|
|
P3RX_HOLD_CMD(LUTData, 16);
|
|
for (dwCount2 = 0; dwCount2 < 16; dwCount2++)
|
|
{
|
|
*dmaPtr++ = CHROMA_UPPER_ALPHA(*(DWORD*)lpColorTable++);
|
|
CHECK_FIFO(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"Palette handle is missing for CI8 surf!"));
|
|
}
|
|
}
|
|
|
|
// Make sure there is room left over for the rest of the routine
|
|
P3_ENSURE_DX_SPACE(2);
|
|
WAIT_FIFO(2);
|
|
SEND_P3_DATA(LUTIndex, 0);
|
|
|
|
}
|
|
else
|
|
#endif // DX7_PALETTETEXTURE
|
|
{
|
|
// No LUT.
|
|
P3_ENSURE_DX_SPACE(4);
|
|
WAIT_FIFO(4);
|
|
|
|
pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_DISABLE;
|
|
SEND_P3_DATA(LUTTransfer, __PERMEDIA_DISABLE);
|
|
COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode)
|
|
}
|
|
|
|
#if DX8_3DTEXTURES
|
|
P3_ENSURE_DX_SPACE(4);
|
|
WAIT_FIFO(4);
|
|
|
|
if (pTexture->b3DTexture)
|
|
{
|
|
//
|
|
// Set size of each 2D texture slice in texel size to TextureMapSize.
|
|
//
|
|
SEND_P3_DATA(TextureMapSize, pTexture->dwSliceInTexel);
|
|
}
|
|
else
|
|
{
|
|
SEND_P3_DATA(TextureMapSize, 0);
|
|
}
|
|
#endif // DX8_3DTEXTURES
|
|
|
|
P3_DMA_COMMIT_BUFFER();
|
|
__TXT_ConsiderSrcChromaKey( pContext, pTexture, 0 );
|
|
P3_DMA_GET_BUFFER();
|
|
|
|
// Setup TextureReadMode
|
|
pSoftP3RX->P3RXTextureReadMode0.MapBaseLevel =
|
|
pMipBases->dwTex0MipBase;
|
|
pSoftP3RX->P3RXTextureReadMode0.MapMaxLevel =
|
|
pMipBases->dwTex0MipMax;
|
|
pSoftP3RX->P3RXTextureReadMode0.Width = pTexture->MipLevels[iT0MaxLevel].logWidth;
|
|
pSoftP3RX->P3RXTextureReadMode0.Height = pTexture->MipLevels[iT0MaxLevel].logHeight;
|
|
pSoftP3RX->P3RXTextureReadMode0.TexelSize = pTexture->dwPixelSize;
|
|
|
|
pSoftP3RX->P3RXTextureReadMode0.LogicalTexture =
|
|
__PERMEDIA_DISABLE;
|
|
|
|
// Enable stage 0
|
|
pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_ENABLE;
|
|
|
|
// Never set CombineCaches - chip bug
|
|
pSoftP3RX->P3RXTextureReadMode0.CombineCaches = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureFilterMode.CombineCaches = __PERMEDIA_DISABLE;
|
|
|
|
// Always copy TRM0 to TRM1 in case we are combining the caches
|
|
pSoftP3RX->P3RXTextureReadMode1 = pSoftP3RX->P3RXTextureReadMode0;
|
|
|
|
// Enable the texture index unit
|
|
// (this is a bit like the the texture read)
|
|
pSoftP3RX->P3RXTextureIndexMode0.Width = pTexture->MipLevels[iT0MaxLevel].logWidth;
|
|
pSoftP3RX->P3RXTextureIndexMode0.Height = pTexture->MipLevels[iT0MaxLevel].logHeight;
|
|
|
|
// Set both formats to be equal for texture 0 - this will be correct
|
|
// for single-texture per-pixel mipmap or non-mipmapped with a
|
|
// combined cache. If the second texture is valid it's setup below
|
|
// will set Format1 appropriately.
|
|
|
|
ASSERTDD ( pFormatSurface != NULL,
|
|
"** SetupTextureUnitStage: logic error: "
|
|
"pFormatSurace is NULL" );
|
|
|
|
pSoftP3RX->P3RXTextureFilterMode.Format0 =
|
|
pFormatSurface->FilterFormat;
|
|
pSoftP3RX->P3RXTextureFilterMode.Format1 =
|
|
pFormatSurface->FilterFormat;
|
|
|
|
#if DX8_3DTEXTURES
|
|
if (pTexture->b3DTexture)
|
|
{
|
|
//
|
|
// Enable 3D Texture registers.
|
|
//
|
|
pSoftP3RX->P3RX_P3DeltaMode.Texture3DEnable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureReadMode0.Texture3D = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode0.Texture3DEnable =
|
|
__PERMEDIA_ENABLE;
|
|
|
|
//
|
|
// ReadMode1 and IndexMode1 should have same data as 0.
|
|
//
|
|
pSoftP3RX->P3RXTextureReadMode1 = pSoftP3RX->P3RXTextureReadMode0;
|
|
pSoftP3RX->P3RXTextureIndexMode1 = pSoftP3RX->P3RXTextureIndexMode0;
|
|
|
|
//
|
|
// And put logDepth into IndexMode1.Width.
|
|
//
|
|
pSoftP3RX->P3RXTextureIndexMode1.Width = pTexture->logDepth;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureReadMode0.Texture3D = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode0.Texture3DEnable =
|
|
__PERMEDIA_DISABLE;
|
|
}
|
|
#endif // DX8_3DTEXTURES
|
|
break;
|
|
}
|
|
|
|
// Texture Stage 1
|
|
case 1:
|
|
{
|
|
pSoftP3RX->P3RXTextureFilterMode.ForceAlphaToOne1 =
|
|
pFormatSurface->bAlpha ?
|
|
__PERMEDIA_DISABLE :
|
|
__PERMEDIA_ENABLE;
|
|
|
|
// D3D UV Wrapping
|
|
if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage] &
|
|
D3DWRAP_U)
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapS1 = 1;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapS1 = 0;
|
|
}
|
|
|
|
if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage] &
|
|
D3DWRAP_V)
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapT1 = 1;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.WrapT1 = 0;
|
|
}
|
|
|
|
// U Addressing
|
|
switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSU ))
|
|
{
|
|
case D3DTADDRESS_CLAMP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
|
|
__GLINT_TEXADDRESS_WRAP_CLAMP;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
|
|
break;
|
|
|
|
case D3DTADDRESS_WRAP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
|
|
__GLINT_TEXADDRESS_WRAP_REPEAT;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_REPEAT;
|
|
break;
|
|
|
|
case D3DTADDRESS_MIRROR:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
|
|
__GLINT_TEXADDRESS_WRAP_MIRROR;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapU =
|
|
P3RX_TEXINDEXMODE_WRAP_MIRROR;
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSU!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
|
|
break;
|
|
}
|
|
|
|
// V Addressing
|
|
switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSV ))
|
|
{
|
|
case D3DTADDRESS_CLAMP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapT1 =
|
|
__GLINT_TEXADDRESS_WRAP_CLAMP;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapV =
|
|
P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
|
|
break;
|
|
|
|
case D3DTADDRESS_WRAP:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapT1 =
|
|
__GLINT_TEXADDRESS_WRAP_REPEAT;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapV =
|
|
P3RX_TEXINDEXMODE_WRAP_REPEAT;
|
|
break;
|
|
|
|
case D3DTADDRESS_MIRROR:
|
|
pSoftP3RX->P3RXTextureCoordMode.WrapT1 =
|
|
__GLINT_TEXADDRESS_WRAP_MIRROR;
|
|
pSoftP3RX->P3RXTextureIndexMode1.WrapV =
|
|
P3RX_TEXINDEXMODE_WRAP_MIRROR;
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSV!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
|
|
break;
|
|
}
|
|
|
|
if(( TSSTATE( iTSStage, D3DTSS_ADDRESSU ) == D3DTADDRESS_CLAMP ) ||
|
|
( TSSTATE( iTSStage, D3DTSS_ADDRESSV ) == D3DTADDRESS_CLAMP ))
|
|
{
|
|
if ((TSSTATE( iTSStage, D3DTSS_ADDRESSU ) != D3DTADDRESS_CLAMP) ||
|
|
(TSSTATE( iTSStage, D3DTSS_ADDRESSV ) != D3DTADDRESS_CLAMP))
|
|
{
|
|
DISPDBG((ERRLVL,"Warning: One texture coord clamped, but not "
|
|
"the other - can't appply TextureShift"));
|
|
}
|
|
|
|
pSoftP3RX->P4DeltaFormatControl.TextureShift1 =
|
|
__PERMEDIA_DISABLE;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P4DeltaFormatControl.TextureShift1 =
|
|
__PERMEDIA_ENABLE;
|
|
}
|
|
|
|
ASSERTDD ( pFormatSurface != NULL,
|
|
"** SetupTextureUnitStage: logic error: "
|
|
"pFormatSurace is NULL" );
|
|
switch (pFormatSurface->DeviceFormat)
|
|
{
|
|
case SURF_CI8:
|
|
pSoftP3RX->P3RXTextureReadMode1.TextureType =
|
|
P3RX_TEXREADMODE_TEXTURETYPE_8BITINDEXED;
|
|
break;
|
|
|
|
case SURF_YUV422:
|
|
pSoftP3RX->P3RXTextureReadMode1.TextureType =
|
|
P3RX_TEXREADMODE_TEXTURETYPE_422_YVYU;
|
|
break;
|
|
|
|
default:
|
|
pSoftP3RX->P3RXTextureReadMode1.TextureType =
|
|
P3RX_TEXREADMODE_TEXTURETYPE_NORMAL;
|
|
break;
|
|
}
|
|
|
|
// MAG Filter
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MAGFILTER ))
|
|
{
|
|
case D3DTFG_POINT:
|
|
pSoftP3RX->P3RXTextureIndexMode1.MagnificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEAREST;
|
|
break;
|
|
|
|
case D3DTFG_LINEAR:
|
|
pSoftP3RX->P3RXTextureIndexMode1.MagnificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEAR;
|
|
break;
|
|
|
|
case D3DTFG_FLATCUBIC:
|
|
case D3DTFG_GAUSSIANCUBIC:
|
|
case D3DTFG_ANISOTROPIC:
|
|
DISPDBG((ERRLVL,"ERROR: Unsupported MAGFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown MAGFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
|
|
break;
|
|
}
|
|
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
|
|
{
|
|
case D3DTFN_POINT:
|
|
pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEAREST;
|
|
break;
|
|
case D3DTFN_LINEAR:
|
|
pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEAR;
|
|
break;
|
|
case D3DTFN_ANISOTROPIC:
|
|
DISPDBG((ERRLVL,"ERROR: Unsupported MINFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
|
|
break;
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Unknown MINFILTER!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
|
|
break;
|
|
}
|
|
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MIPFILTER ))
|
|
{
|
|
case D3DTFP_NONE:
|
|
// No need to set the minification filter
|
|
// it was done above
|
|
break;
|
|
|
|
case D3DTFP_LINEAR:
|
|
case D3DTFP_POINT:
|
|
if( bBothTexturesValid )
|
|
{
|
|
if ( TSSTATE ( iTSStage, D3DTSS_MIPFILTER ) ==
|
|
D3DTFP_LINEAR )
|
|
{
|
|
// Can't do trilinear with both textures
|
|
// - fall back to per-poly.
|
|
SET_BLEND_ERROR ( pContext, BS_INVALID_FILTER );
|
|
}
|
|
|
|
// We can only do per-poly mipmapping while
|
|
// multi-texturing, so don't enable
|
|
//inter-map filtering.
|
|
|
|
switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
|
|
{
|
|
case D3DTFN_POINT:
|
|
// Point Min, Point Mip
|
|
pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_NEARMIPNEAREST;
|
|
break;
|
|
|
|
case D3DTFN_LINEAR:
|
|
// Linear Min, Point Mip
|
|
pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
|
|
__GLINT_TEXTUREREAD_FILTER_LINEARMIPNEAREST;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"** Setting up the second stage, but "
|
|
"only one texture is valid"));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DISPDBG((ERRLVL,"ERROR: Invalid Mip filter!"));
|
|
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
|
|
break;
|
|
}
|
|
|
|
// MipMapping
|
|
// If the app chooses to have two mip-mapped textures or a
|
|
// single mip-mapped texture in stage 1 they only get
|
|
// per-poly mipmapping.
|
|
if( (TSSTATE ( iTSStage, D3DTSS_MIPFILTER ) != D3DTFP_NONE) &&
|
|
pTexture->bMipMap )
|
|
{
|
|
int iLOD, iTexLOD;
|
|
|
|
// Load the mipmap levels for texture 1
|
|
// Mip level from pMipBases->dwTex1ActMaxLevel to
|
|
// pTexture->iMipLevels will be mapped to base address slot
|
|
// from pMipBases->dwTex1Mipbase to dwTex1MipMax
|
|
iLOD = pMipBases->dwTex1MipBase;
|
|
iTexLOD = pMipBases->dwTex1ActMaxLevel;
|
|
iT1MaxLevel = iTexLOD;
|
|
|
|
P3_ENSURE_DX_SPACE(32);
|
|
WAIT_FIFO(32);
|
|
|
|
while(( iTexLOD < pTexture->iMipLevels ) &&
|
|
( iLOD <= (int)pMipBases->dwTex1MipMax ))
|
|
{
|
|
DISPDBG((DBGLVL, " Setting Texture Base Address %d to 0x%x",
|
|
iLOD,
|
|
pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase));
|
|
|
|
pSoftP3RX->P3RXTextureMapWidth[iLOD] =
|
|
pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
|
|
|
|
#if DX7_TEXMANAGEMENT
|
|
// If this is a driver managed texture surface, we need
|
|
// to use our privately allocated mem ptr
|
|
if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
(DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
|
|
iLOD);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
|
|
iLOD);
|
|
}
|
|
|
|
iLOD++;
|
|
iTexLOD++;
|
|
}
|
|
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableLOD = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableDY = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap1 =
|
|
__PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode1.MipMapEnable =
|
|
__PERMEDIA_ENABLE;
|
|
|
|
P3_ENSURE_DX_SPACE(2);
|
|
WAIT_FIFO(2);
|
|
{
|
|
DWORD d;
|
|
|
|
*(float *)&d =
|
|
pContext->MipMapLODBias[TEXSTAGE_1] *
|
|
pTexture->dwPixelPitch *
|
|
pTexture->wHeight;
|
|
|
|
SEND_P3_DATA(TextureLODScale1, d);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int iTexLOD;
|
|
|
|
// Use the maximum level indicated by D3DTSS_MAXMIPLEVEL
|
|
iTexLOD = pMipBases->dwTex0ActMaxLevel;
|
|
iT1MaxLevel = iTexLOD;
|
|
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableLOD = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCoordMode.EnableDY = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap1 =
|
|
__PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode1.MipMapEnable =
|
|
__PERMEDIA_DISABLE;
|
|
|
|
P3_ENSURE_DX_SPACE(2);
|
|
WAIT_FIFO(2);
|
|
|
|
#if DX7_TEXMANAGEMENT
|
|
// If this is a driver managed texture surface, we need
|
|
// to use our privately allocated mem ptr
|
|
if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
(DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
|
|
pMipBases->dwTex1MipBase);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SEND_P3_DATA_OFFSET(TextureBaseAddr0,
|
|
pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
|
|
pMipBases->dwTex1MipBase);
|
|
}
|
|
|
|
// No mipmapping.
|
|
pSoftP3RX->P3RXTextureMapWidth[pMipBases->dwTex1MipBase] =
|
|
pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
|
|
}
|
|
|
|
|
|
ASSERTDD ( pFormatSurface != NULL,
|
|
"** SetupTextureUnitStage: logic error: "
|
|
"pFormatSurace is NULL" );
|
|
|
|
if (pFormatSurface->DeviceFormat == SURF_CI8)
|
|
{
|
|
// In the future, this will work as long as texture 0 isn't
|
|
// palettised, or if they share the palette.
|
|
// But that needs some restructuring - the whole LUT setup
|
|
// should be in a single bit of code in _D3DChangeTextureP3RX,
|
|
// since it is a shared resource.
|
|
DISPDBG((ERRLVL,"** SetupTextureUnitStage: allow second texture "
|
|
"to use LUTs"));
|
|
|
|
// For now, fail.
|
|
SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_PALETTES );
|
|
}
|
|
|
|
P3_DMA_COMMIT_BUFFER();
|
|
__TXT_ConsiderSrcChromaKey( pContext, pTexture, 1 );
|
|
P3_DMA_GET_BUFFER();
|
|
|
|
// Setup TextureReadMode
|
|
pSoftP3RX->P3RXTextureReadMode1.MapBaseLevel =
|
|
pMipBases->dwTex1MipBase;
|
|
pSoftP3RX->P3RXTextureReadMode1.MapMaxLevel =
|
|
pMipBases->dwTex1MipMax;
|
|
pSoftP3RX->P3RXTextureReadMode1.Width = pTexture->MipLevels[iT1MaxLevel].logWidth;
|
|
pSoftP3RX->P3RXTextureReadMode1.Height = pTexture->MipLevels[iT1MaxLevel].logHeight;
|
|
pSoftP3RX->P3RXTextureReadMode1.TexelSize = pTexture->dwPixelSize;
|
|
|
|
pSoftP3RX->P3RXTextureReadMode1.LogicalTexture =
|
|
__PERMEDIA_DISABLE;
|
|
|
|
// Enable the texture index unit (this is a bit like the
|
|
// the texture read)
|
|
pSoftP3RX->P3RXTextureIndexMode1.Width = pTexture->MipLevels[iT1MaxLevel].logWidth;
|
|
pSoftP3RX->P3RXTextureIndexMode1.Height = pTexture->MipLevels[iT1MaxLevel].logHeight;
|
|
ASSERTDD ( pFormatSurface != NULL,
|
|
"** SetupTextureUnitStage: logic error: "
|
|
"pFormatSurace is NULL" );
|
|
pSoftP3RX->P3RXTextureFilterMode.Format1 =
|
|
pFormatSurface->FilterFormat;
|
|
|
|
// Enable stage 1
|
|
pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_ENABLE;
|
|
|
|
#if DX7_PALETTETEXTURE
|
|
#if 0
|
|
// D3DValidateDeviceP3() will return error code for this case
|
|
ASSERTDD((pFormatSurface->DeviceFormat != SURF_CI8 &&
|
|
pFormatSurface->DeviceFormat != SURF_CI4),
|
|
"Texture surface can't be palettized when using a "
|
|
"second map!");
|
|
#endif
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
P3_DMA_COMMIT_BUFFER();
|
|
|
|
return TRUE;
|
|
} // __TXT_SetupTexture
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// __bD3DTexturesMatch
|
|
//
|
|
//
|
|
// A function to compare the two textures in two D3D stages, and determine
|
|
// if they could be satisfied by the same on-chip texture.
|
|
//
|
|
// int iStage1 D3D stage number of first texture.
|
|
// int iStage2 D3D stage number of second texture.
|
|
// *pContext The context.
|
|
//
|
|
// result: TRUE if the textures match, FALSE if they don't.
|
|
//
|
|
// An ASSERT is triggered if either stage is not using a texture. In the
|
|
// release build, the result will be TRUE, meaning that we could pack both
|
|
// textures stages requirements into one texture (because one or both do
|
|
// not use a texture).
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
BOOL
|
|
__bD3DTexturesMatch (
|
|
int iStage1,
|
|
int iStage2,
|
|
P3_D3DCONTEXT* pContext )
|
|
{
|
|
ASSERTDD ( iStage1 != iStage2,
|
|
"** __bD3DTexturesMatch: both stages are the same "
|
|
"- pointless comparison!" );
|
|
|
|
if ( TSSTATE ( iStage1, D3DTSS_TEXTUREMAP ) == 0 )
|
|
{
|
|
DISPDBG((ERRLVL,"** __bD3DTexturesMatch: first considered stage's "
|
|
"texture is NULL"));
|
|
|
|
return ( TRUE );
|
|
}
|
|
else if ( TSSTATE ( iStage2, D3DTSS_TEXTUREMAP ) == 0 )
|
|
{
|
|
DISPDBG((ERRLVL,"** __bD3DTexturesMatch: second considered stage's "
|
|
"texture is NULL"));
|
|
return ( TRUE );
|
|
}
|
|
else
|
|
{
|
|
#define CHECK_EQUALITY(name) ( TSSTATE ( iStage1, name ) == TSSTATE ( iStage2, name ) )
|
|
if (CHECK_EQUALITY ( D3DTSS_TEXTUREMAP ) &&
|
|
CHECK_EQUALITY ( D3DTSS_TEXCOORDINDEX ) )
|
|
{
|
|
// Yes, the textures have the same handle and coord set. Do
|
|
// some further checks.
|
|
|
|
// If the pointers are different, or the texcoord sets are
|
|
// different (for bumpmapping), this is a common occurrance,
|
|
// and need not be flagged. However, if they are the same,
|
|
// but a filter mode or something like that is different,
|
|
// it is likely to be an app bug, so flag it.
|
|
|
|
if (
|
|
// Should not need to check ADDRESS
|
|
// - should have been mirrored to ADDRESS[UV].
|
|
CHECK_EQUALITY ( D3DTSS_ADDRESSU ) &&
|
|
CHECK_EQUALITY ( D3DTSS_ADDRESSV ) &&
|
|
CHECK_EQUALITY ( D3DTSS_MAGFILTER ) &&
|
|
CHECK_EQUALITY ( D3DTSS_MINFILTER ) &&
|
|
CHECK_EQUALITY ( D3DTSS_MIPFILTER ) )
|
|
// I should also check all the other variables like
|
|
// MIPMAPLODBIAS, but they rely on mipmapping being
|
|
// enabled, etc, so it's more of a hassle. If an app
|
|
// really does manage to be this perverse, it's doing well!
|
|
{
|
|
// Looks good.
|
|
return ( TRUE );
|
|
}
|
|
else
|
|
{
|
|
// Well, the texcoords agree and the handle agree, but the
|
|
// others don't. I bet this is an app bug - you are unlikely
|
|
// to do this deliberately.
|
|
_D3DDisplayWholeTSSPipe ( pContext, WRNLVL );
|
|
DISPDBG((ERRLVL,"** __bD3DTexturesMatch: textures agree in "
|
|
"handle and texcoord, but not other things - "
|
|
"likely app bug."));
|
|
return ( FALSE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No, different textures.
|
|
return ( FALSE );
|
|
}
|
|
#undef CHECK_EQUALITY
|
|
}
|
|
return TRUE;
|
|
} // __bD3DTexturesMatch
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// _D3DChangeTextureP3RX
|
|
//
|
|
// This function does whole setup of necessary texturing state according to
|
|
// the current renderestates and texture stage states. Disables texturing
|
|
// accordingly if this is needed.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void
|
|
_D3DChangeTextureP3RX(
|
|
P3_D3DCONTEXT* pContext)
|
|
{
|
|
P3_SURF_INTERNAL* pTexture0 = NULL;
|
|
P3_SURF_INTERNAL* pTexture1 = NULL;
|
|
P3_THUNKEDDATA * pThisDisplay = pContext->pThisDisplay;
|
|
P3_SOFTWARECOPY* pSoftP3RX = &pContext->SoftCopyGlint;
|
|
P3_MIP_BASES mipBases;
|
|
DWORD* pFlags = &pContext->Flags;
|
|
INT i, iLastChipStage;
|
|
DWORD dwT0MipLevels,
|
|
dwT1MipLevels,
|
|
dwTexAppTfactor,
|
|
dwTexComp0Tfactor,
|
|
dwTexComp1Tfactor;
|
|
BOOL bBothTexturesValid,
|
|
bProcessChipStage0,
|
|
bProcessChipStage1,
|
|
bProcessChipStage2,
|
|
bAlphaBlendDouble;
|
|
|
|
P3_DMA_DEFS();
|
|
|
|
DBG_ENTRY(_D3DChangeTextureP3RX);
|
|
|
|
pContext->iTexStage[0] = -1;
|
|
pContext->iTexStage[1] = -1;
|
|
// This is checked against the current state at the end of the routine.
|
|
bAlphaBlendDouble = FALSE;
|
|
|
|
// Verify if texturing should be disabled
|
|
if ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_DISABLE ) ||
|
|
( ( TSSTATE ( TEXSTAGE_0, D3DTSS_TEXTUREMAP ) == 0 ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) == D3DTOP_DISABLE ) &&
|
|
( ( ( TSSTATESELECT ( TEXSTAGE_0, D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ) ||
|
|
( ( TSSTATESELECT ( TEXSTAGE_0, D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ) )
|
|
) )
|
|
{
|
|
// Stage 0 is disabled, so they just want the diffuse colour.
|
|
// Or, the texture handle is 0 , stage 1 is D3DTOP_DISABLE and in stage
|
|
// 0 we are selecting an arg that is not a D3DTA_TEXTURE
|
|
|
|
DISPDBG((DBGLVL, "All composite units disabled - setting diffuse colour"));
|
|
|
|
P3_DMA_GET_BUFFER_ENTRIES(20);
|
|
|
|
// Turn off texture address generation
|
|
pSoftP3RX->P3RXTextureCoordMode.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureCoordMode, pSoftP3RX->P3RXTextureCoordMode);
|
|
|
|
// Turn off texture reads
|
|
pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureReadMode0, pSoftP3RX->P3RXTextureReadMode0);
|
|
COPY_P3_DATA(TextureReadMode1, pSoftP3RX->P3RXTextureReadMode1);
|
|
pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureIndexMode0, pSoftP3RX->P3RXTextureIndexMode0);
|
|
COPY_P3_DATA(TextureIndexMode1, pSoftP3RX->P3RXTextureIndexMode1);
|
|
|
|
// Turn off the texture filter mode unit
|
|
pSoftP3RX->P3RXTextureFilterMode.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureFilterMode, pSoftP3RX->P3RXTextureFilterMode);
|
|
|
|
// Turn off texture color mode unit
|
|
pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureApplicationMode,
|
|
pSoftP3RX->P3RXTextureApplicationMode);
|
|
|
|
// Not compositing
|
|
SEND_P3_DATA(TextureCompositeMode, __PERMEDIA_DISABLE);
|
|
|
|
*pFlags &= ~SURFACE_TEXTURING;
|
|
|
|
pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode);
|
|
|
|
// Specular texture can be enabled without texturing on
|
|
COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
|
|
|
|
P3_DMA_COMMIT_BUFFER();
|
|
|
|
// Turn off texturing in the render command
|
|
RENDER_TEXTURE_DISABLE(pContext->RenderCommand);
|
|
|
|
pContext->bTextureValid = TRUE;
|
|
pContext->pCurrentTexture[0] = NULL;
|
|
pContext->pCurrentTexture[1] = NULL;
|
|
|
|
// Track just for debugging purpouses
|
|
pContext->bTexDisabled = TRUE;
|
|
|
|
bAlphaBlendDouble = FALSE;
|
|
if ( bAlphaBlendDouble != pContext->bAlphaBlendMustDoubleSourceColour )
|
|
{
|
|
pContext->bAlphaBlendMustDoubleSourceColour = bAlphaBlendDouble;
|
|
DIRTY_ALPHABLEND(pContext);
|
|
}
|
|
|
|
DBG_EXIT(_D3DChangeTextureP3RX,1);
|
|
return;
|
|
}
|
|
|
|
if ( TSSTATE ( TEXSTAGE_0, D3DTSS_TEXTUREMAP ) == 0 )
|
|
if ( ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG1 ) == D3DTA_TFACTOR ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) ) ||
|
|
( ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG2 ) == D3DTA_TFACTOR ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_SELECTARG2 ) ) )
|
|
{
|
|
// This is an unusual way to set up the diffuse color : take
|
|
// it from the the D3DTA_TFACTOR. But some apps use it.
|
|
// we need to treat it separately for the Perm3 setup because
|
|
// it might not be binded with any texture
|
|
|
|
DISPDBG((DBGLVL, "Diffuse color comes from D3DTA_TFACTOR"));
|
|
|
|
P3_DMA_GET_BUFFER_ENTRIES(30);
|
|
|
|
// Turn off texture address generation
|
|
pSoftP3RX->P3RXTextureCoordMode.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureCoordMode, pSoftP3RX->P3RXTextureCoordMode);
|
|
|
|
// Turn off texture reads
|
|
pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureReadMode0, pSoftP3RX->P3RXTextureReadMode0);
|
|
COPY_P3_DATA(TextureReadMode1, pSoftP3RX->P3RXTextureReadMode1);
|
|
pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureIndexMode0, pSoftP3RX->P3RXTextureIndexMode0);
|
|
COPY_P3_DATA(TextureIndexMode1, pSoftP3RX->P3RXTextureIndexMode1);
|
|
|
|
// Turn off the texture filter mode unit
|
|
pSoftP3RX->P3RXTextureFilterMode.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureFilterMode, pSoftP3RX->P3RXTextureFilterMode);
|
|
|
|
// Setup texture color mode unit
|
|
pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorA = P3RX_TEXAPP_A_KC;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorOperation = P3RX_TEXAPP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaA = P3RX_TEXAPP_A_KA;
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaOperation = P3RX_TEXAPP_OPERATION_PASS_A;
|
|
|
|
COPY_P3_DATA(TextureApplicationMode,
|
|
pSoftP3RX->P3RXTextureApplicationMode);
|
|
|
|
// Setup compositing
|
|
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_FA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
COPY_P3_DATA(TextureCompositeAlphaMode0,
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0);
|
|
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_FC;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
COPY_P3_DATA(TextureCompositeColorMode0,
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0);
|
|
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureCompositeAlphaMode1,
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1);
|
|
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(TextureCompositeColorMode1,
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1);
|
|
|
|
SEND_P3_DATA(TextureCompositeMode, __PERMEDIA_ENABLE);
|
|
|
|
*pFlags &= ~SURFACE_TEXTURING;
|
|
|
|
pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_DISABLE;
|
|
COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode);
|
|
|
|
// Specular texture can be enabled without texturing on
|
|
COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
|
|
|
|
P3_DMA_COMMIT_BUFFER();
|
|
|
|
|
|
|
|
// Turn off texturing in the render command
|
|
// RENDER_TEXTURE_DISABLE(pContext->RenderCommand);
|
|
RENDER_TEXTURE_ENABLE(pContext->RenderCommand);
|
|
|
|
pContext->bTextureValid = TRUE;
|
|
pContext->pCurrentTexture[0] = NULL;
|
|
pContext->pCurrentTexture[1] = NULL;
|
|
|
|
// Track just for debugging purpouses
|
|
pContext->bTexDisabled = FALSE;
|
|
|
|
|
|
DBG_EXIT(_D3DChangeTextureP3RX,1);
|
|
return;
|
|
}
|
|
|
|
// Track just for debugging purpouses
|
|
pContext->bTexDisabled = FALSE;
|
|
|
|
// Dump to the debugger our current TSS setup
|
|
_D3DDisplayWholeTSSPipe(pContext, DBGLVL);
|
|
|
|
// Deal with the textures.
|
|
|
|
// Find the texture mappings. If D3D stage 0 uses a texture, it must
|
|
// always be chip texture 0 to keep the bumpmap working. Fortunately,
|
|
// this is the only non-orthogonal case, so everything else can cope
|
|
// with this restriction.
|
|
|
|
for ( i = TEXSTAGE_0; i < D3DTSS_MAX; i++ )
|
|
{
|
|
if ( TSSTATE ( i, D3DTSS_COLOROP ) == D3DTOP_DISABLE )
|
|
{
|
|
// Finished processing.
|
|
break;
|
|
}
|
|
|
|
// This code could be slightly optimised - if a texture is set up,
|
|
// but none of the relevant arguments are TEXTURE (with additional
|
|
// flags), then of course we don't need to set the texture up at all.
|
|
// Normally, both arguments are "relevant", but with SELECTARG1 and
|
|
// SELECTARG2, one of them is not. Also, watch out for PREMODULATE -
|
|
// it is an implicit reference to a stage's texture.
|
|
|
|
if (
|
|
( TSSTATE ( i, D3DTSS_TEXTUREMAP ) == 0 ) ||
|
|
( (
|
|
( ( TSSTATESELECT ( i, D3DTSS_COLORARG1 ) != D3DTA_TEXTURE ) ||
|
|
( TSSTATE ( i, D3DTSS_COLOROP ) == D3DTOP_SELECTARG2 ) ) &&
|
|
( ( TSSTATESELECT ( i, D3DTSS_COLORARG2 ) != D3DTA_TEXTURE ) ||
|
|
( TSSTATE ( i, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) ) &&
|
|
( ( TSSTATESELECT ( i, D3DTSS_ALPHAARG1 ) != D3DTA_TEXTURE ) ||
|
|
( TSSTATE ( i, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) ) &&
|
|
( ( TSSTATESELECT ( i, D3DTSS_ALPHAARG2 ) != D3DTA_TEXTURE ) ||
|
|
( TSSTATE ( i, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) )
|
|
) &&
|
|
( TSSTATE ( i, D3DTSS_COLOROP ) != D3DTOP_PREMODULATE ) &&
|
|
( TSSTATE ( i-1, D3DTSS_COLOROP ) != D3DTOP_PREMODULATE )
|
|
) )
|
|
{
|
|
// This D3D stage doesn't use a texture.
|
|
pContext->iStageTex[i] = -1;
|
|
}
|
|
else
|
|
{
|
|
// Note that the below code should be put into a little loop
|
|
// for any future devices that have more than 2 textures, otherwise
|
|
// the code will get big, nested and crufty. But for only 2, it's
|
|
// manageable, and slightly faster this way.
|
|
|
|
// A texture is used - is texture 0 free?
|
|
if ( pContext->iTexStage[0] == -1 )
|
|
{
|
|
// Texture 0 is free - make it this stage.
|
|
ASSERTDD ( pContext->iTexStage[1] == -1,
|
|
"** _D3DChangeTextureP3RX: pContext->iTexStage[1] "
|
|
"should be -1 if pContext->iTexStage[0] is" );
|
|
pContext->iTexStage[0] = i;
|
|
pContext->iStageTex[i] = 0;
|
|
}
|
|
else
|
|
{
|
|
// Texture 0 is assigned - see if this is the same as it.
|
|
if ( __bD3DTexturesMatch ( i,
|
|
pContext->iTexStage[0],
|
|
pContext ) )
|
|
{
|
|
// Yes, they match - no need to use texture 1.
|
|
pContext->iStageTex[i] = 0;
|
|
}
|
|
else
|
|
{
|
|
// No, they don't match. Is texture 1 free?
|
|
if ( pContext->iTexStage[1] == -1 )
|
|
{
|
|
// Texture 1 is free - make it this stage.
|
|
ASSERTDD ( pContext->iTexStage[0] != -1,
|
|
"** _D3DChangeTextureP3RX: "
|
|
"pContext->iTexStage[0] should not be "
|
|
"-1 if pContext->iTexStage[1] is not." );
|
|
pContext->iTexStage[1] = i;
|
|
pContext->iStageTex[i] = 1;
|
|
}
|
|
else
|
|
{
|
|
// Texture 1 is assigned - see if this is the same
|
|
// as it.
|
|
if ( __bD3DTexturesMatch ( i,
|
|
pContext->iTexStage[1],
|
|
pContext ) )
|
|
{
|
|
// Yes, they match - mark it.
|
|
pContext->iStageTex[i] = 1;
|
|
}
|
|
else
|
|
{
|
|
// No, they don't match, and both chip textures
|
|
// have been assigned. Fail a ValidateDevice().
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: app tried "
|
|
"to use more than two textures."));
|
|
SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_TEXTURES );
|
|
pContext->iStageTex[i] = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// A quick sanity check.
|
|
#if DBG
|
|
if ( TSSTATE ( i, D3DTSS_TEXTUREMAP ) == 0 )
|
|
{
|
|
// That's fine, then.
|
|
ASSERTDD ( pContext->iStageTex[i] == -1,
|
|
"** _D3DChangeTextureP3RX: something failed with the "
|
|
"texture-assignment logic" );
|
|
}
|
|
else if ( pContext->iStageTex[i] == -1 )
|
|
{
|
|
// That's fine - texture may have been set up but not referenced.
|
|
}
|
|
else if ( pContext->iTexStage[pContext->iStageTex[i]] == -1 )
|
|
{
|
|
// Oops.
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: something failed with "
|
|
"the texture-assignment logic"));
|
|
}
|
|
else if ( pContext->iTexStage[pContext->iStageTex[i]] == i )
|
|
{
|
|
// That's fine, then.
|
|
}
|
|
else if ( __bD3DTexturesMatch ( i,
|
|
pContext->iTexStage[pContext->iStageTex[i]],
|
|
pContext ) )
|
|
{
|
|
// That's fine, then.
|
|
}
|
|
else
|
|
{
|
|
// Oops.
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: something failed with "
|
|
"the texture-assignment logic"));
|
|
}
|
|
#endif // DBG
|
|
}
|
|
|
|
// And a few more gratuitous sanity checks at the end of the loop.
|
|
ASSERTDD ( ( pContext->iTexStage[0] == -1 ) ||
|
|
( pContext->iStageTex[pContext->iTexStage[0]] == 0 ),
|
|
"** _D3DChangeTextureP3RX: something failed with the "
|
|
"texture-assignment logic" );
|
|
|
|
ASSERTDD ( ( pContext->iTexStage[1] == -1 ) ||
|
|
( pContext->iStageTex[pContext->iTexStage[1]] == 1 ),
|
|
"** _D3DChangeTextureP3RX: something failed with the "
|
|
"texture-assignment logic" );
|
|
|
|
#if DBG
|
|
if ( pContext->iTexStage[0] != -1 )
|
|
{
|
|
DISPDBG((DBGLVL, "Setting new texture0 data, Handle: 0x%x",
|
|
TSSTATE ( pContext->iTexStage[0], D3DTSS_TEXTUREMAP )));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((DBGLVL, "Texture0 not used" ));
|
|
}
|
|
|
|
if ( pContext->iTexStage[1] != -1 )
|
|
{
|
|
DISPDBG((DBGLVL, "Setting new texture1 data, Handle: 0x%x",
|
|
TSSTATE ( pContext->iTexStage[1], D3DTSS_TEXTUREMAP )));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((DBGLVL, "Texture1 not used" ));
|
|
}
|
|
#endif //DBG
|
|
|
|
// Set the texture valid flag to true.
|
|
// If anything resets it then the texture state is invalid.
|
|
pContext->bTextureValid = TRUE;
|
|
pContext->bCanChromaKey = FALSE;
|
|
pContext->bTex0Valid = FALSE;
|
|
pContext->bTex1Valid = FALSE;
|
|
pContext->bStage0DotProduct = FALSE;
|
|
|
|
// Set up the textures.
|
|
if ( pContext->iTexStage[0] != -1 )
|
|
{
|
|
// Setup texture 0.
|
|
pTexture0 = GetSurfaceFromHandle(pContext,
|
|
TSSTATE(pContext->iTexStage[0],
|
|
D3DTSS_TEXTUREMAP) );
|
|
if (NULL == pTexture0)
|
|
{
|
|
DISPDBG((ERRLVL, "ERROR: Texture Surface (0) is NULL"));
|
|
DBG_EXIT(_D3DChangeTextureP3RX,1);
|
|
return;
|
|
}
|
|
|
|
#if DX7_TEXMANAGEMENT
|
|
if (pTexture0->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
|
|
{
|
|
if (!_D3D_TM_Preload_Tex_IntoVidMem(pContext, pTexture0))
|
|
{
|
|
return; // something bad happened !!!
|
|
}
|
|
|
|
_D3D_TM_TimeStampTexture(pContext->pTextureManager,
|
|
pTexture0);
|
|
}
|
|
#endif // DX7_TEXMANAGEMENT
|
|
|
|
pContext->bTex0Valid =
|
|
__TXT_ValidateTextureUnitStage(pContext,
|
|
0,
|
|
pContext->iTexStage[0],
|
|
pTexture0 );
|
|
if ( !pContext->bTex0Valid )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_INVALID_TEXTURE );
|
|
// Pretend that no texture was set.
|
|
pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
|
|
pContext->bTex0Valid = FALSE;
|
|
pTexture0 = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
|
|
pContext->bTex0Valid = FALSE;
|
|
pTexture0 = NULL;
|
|
}
|
|
|
|
if ( pContext->iTexStage[1] != -1 )
|
|
{
|
|
// Setup texture 1.
|
|
if ( pContext->iTexStage[0] == -1 )
|
|
{
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: Should not be "
|
|
"using tex1 if tex0 not used."));
|
|
SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_BLEND_STAGES );
|
|
}
|
|
|
|
pTexture1 = GetSurfaceFromHandle(pContext,
|
|
TSSTATE ( pContext->iTexStage[1],
|
|
D3DTSS_TEXTUREMAP ) );
|
|
if (NULL == pTexture1)
|
|
{
|
|
DISPDBG((ERRLVL, "ERROR: Texture Surface (1) is NULL"));
|
|
DBG_EXIT(_D3DChangeTextureP3RX,1);
|
|
return;
|
|
}
|
|
|
|
|
|
#if DX7_TEXMANAGEMENT
|
|
if (pTexture1->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
|
|
{
|
|
if (!_D3D_TM_Preload_Tex_IntoVidMem(pContext, pTexture1))
|
|
{
|
|
return; // something bad happened !!!
|
|
}
|
|
|
|
_D3D_TM_TimeStampTexture(pContext->pTextureManager,
|
|
pTexture1);
|
|
}
|
|
#endif // DX7_TEXMANAGEMENT
|
|
|
|
pContext->bTex1Valid =
|
|
__TXT_ValidateTextureUnitStage(pContext,
|
|
1,
|
|
pContext->iTexStage[1],
|
|
pTexture1 );
|
|
if ( !pContext->bTex1Valid )
|
|
{
|
|
SET_BLEND_ERROR ( pContext, BSF_INVALID_TEXTURE );
|
|
// Pretend that no texture was set.
|
|
pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
|
|
pContext->bTex1Valid = FALSE;
|
|
pTexture1 = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
|
|
pContext->bTex1Valid = FALSE;
|
|
pTexture1 = NULL;
|
|
}
|
|
|
|
bBothTexturesValid = pContext->bTex0Valid && pContext->bTex1Valid;
|
|
|
|
if( pContext->bTex0Valid )
|
|
{
|
|
dwT0MipLevels = pContext->TextureStageState[0].m_dwVal[D3DTSS_MAXMIPLEVEL];
|
|
#if DX7_TEXMANAGEMENT
|
|
if ( dwT0MipLevels < pTexture0->m_dwTexLOD)
|
|
{
|
|
dwT0MipLevels = pTexture0->m_dwTexLOD;
|
|
}
|
|
#endif // DX7_TEXMANAGEMENT
|
|
if (dwT0MipLevels > ((DWORD)(pTexture0->iMipLevels - 1)))
|
|
{
|
|
// Set the actuall maximum mip level that will be used in rendering
|
|
mipBases.dwTex0ActMaxLevel = pTexture0->iMipLevels - 1;
|
|
|
|
dwT0MipLevels = 1;
|
|
}
|
|
else
|
|
{
|
|
// Set the actuall maximum mip level that will be used in rendering
|
|
mipBases.dwTex0ActMaxLevel = dwT0MipLevels;
|
|
|
|
dwT0MipLevels = pTexture0->iMipLevels - dwT0MipLevels;
|
|
}
|
|
}
|
|
|
|
if( pContext->bTex1Valid )
|
|
{
|
|
ASSERTDD ( pContext->bTex0Valid,
|
|
"** _D3DChangeTextureP3RX: tex1 should not be used "
|
|
"unless tex0 is used as well" );
|
|
|
|
dwT1MipLevels = pContext->TextureStageState[1].m_dwVal[D3DTSS_MAXMIPLEVEL];
|
|
#if DX7_TEXMANAGEMENT
|
|
if ( dwT1MipLevels < pTexture1->m_dwTexLOD)
|
|
{
|
|
dwT1MipLevels = pTexture1->m_dwTexLOD;
|
|
}
|
|
#endif // DX7_TEXMANAGEMENT
|
|
if (dwT1MipLevels > ((DWORD)(pTexture1->iMipLevels - 1)))
|
|
{
|
|
// Set the actuall maximum mip level that will be used in rendering
|
|
mipBases.dwTex1ActMaxLevel = pTexture1->iMipLevels - 1;
|
|
|
|
dwT1MipLevels = 1;
|
|
}
|
|
else
|
|
{
|
|
// Set the actuall maximum mip level that will be used in rendering
|
|
mipBases.dwTex1ActMaxLevel = dwT1MipLevels;
|
|
|
|
dwT1MipLevels = pTexture1->iMipLevels - dwT1MipLevels;
|
|
}
|
|
|
|
// Enable generation of the second set of texture coordinates.
|
|
// Strictly, we should check whether texture 0 is being used, and
|
|
// if not move the second texture to the first (thus enabling
|
|
// mipmapping, etc) but that's for later.
|
|
pSoftP3RX->P3RX_P3DeltaMode.TextureEnable1 = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RX_P3DeltaControl.ShareQ = 1;
|
|
}
|
|
else
|
|
{
|
|
// Turn off generation of the second set of texture coordinates
|
|
pSoftP3RX->P3RX_P3DeltaMode.TextureEnable1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RX_P3DeltaControl.ShareQ = 0;
|
|
}
|
|
|
|
if( bBothTexturesValid )
|
|
{
|
|
float totBases, baseRatio;
|
|
DWORD t0Count, res;
|
|
|
|
totBases = (float)dwT0MipLevels + dwT1MipLevels;
|
|
|
|
// Adjust mip levels to fit in N - 2 slots as each texture
|
|
// needs at least one slot.
|
|
|
|
baseRatio = ( P3_TEX_MAP_MAX_LEVEL - 1 ) / totBases;
|
|
|
|
// Calculate number of slots for texture 0, texture 1 then
|
|
// gets the remainder.
|
|
|
|
myFtoi( &res, dwT0MipLevels * baseRatio );
|
|
t0Count = 1 + res;
|
|
|
|
ASSERTDD( t0Count > 0, "No slots for texture 0" );
|
|
ASSERTDD( t0Count <= P3_TEX_MAP_MAX_LEVEL, "No slots for texture 1" );
|
|
|
|
#define FIXED_ALLOC 0
|
|
#if FIXED_ALLOC
|
|
mipBases.dwTex0MipBase = 0;
|
|
mipBases.dwTex0MipMax = min( dwT0MipLevels - 1, 7 );
|
|
mipBases.dwTex1MipBase = 8;
|
|
mipBases.dwTex1MipMax = 8 + min( dwT1MipLevels - 1,
|
|
P3_TEX_MAP_MAX_LEVEL - 8 );
|
|
#else
|
|
mipBases.dwTex0MipBase = 0;
|
|
mipBases.dwTex0MipMax = min( dwT0MipLevels - 1, t0Count - 1 );
|
|
mipBases.dwTex1MipBase = t0Count;
|
|
mipBases.dwTex1MipMax = t0Count + min( dwT1MipLevels - 1,
|
|
P3_TEX_MAP_MAX_LEVEL - t0Count );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if( pContext->bTex0Valid )
|
|
{
|
|
mipBases.dwTex0MipBase = 0;
|
|
mipBases.dwTex0MipMax = min( dwT0MipLevels - 1,
|
|
P3_TEX_MAP_MAX_LEVEL );
|
|
mipBases.dwTex1MipBase = 0;
|
|
mipBases.dwTex1MipMax = min( dwT0MipLevels - 1,
|
|
P3_TEX_MAP_MAX_LEVEL );
|
|
}
|
|
|
|
if( pContext->bTex1Valid )
|
|
{
|
|
mipBases.dwTex0MipBase = 0;
|
|
mipBases.dwTex0MipMax = min( dwT1MipLevels - 1,
|
|
P3_TEX_MAP_MAX_LEVEL );
|
|
mipBases.dwTex1MipBase = 0;
|
|
mipBases.dwTex1MipMax = min( dwT1MipLevels - 1,
|
|
P3_TEX_MAP_MAX_LEVEL );
|
|
}
|
|
}
|
|
|
|
DISPDBG(( DBGLVL, "tex0 base %d", mipBases.dwTex0MipBase ));
|
|
DISPDBG(( DBGLVL, "tex0 max %d", mipBases.dwTex0MipMax ));
|
|
DISPDBG(( DBGLVL, "tex1 base %d", mipBases.dwTex1MipBase ));
|
|
DISPDBG(( DBGLVL, "tex1 max %d", mipBases.dwTex1MipMax ));
|
|
|
|
// Recalculate the LOD biases for per-poly mipmapping
|
|
pContext->MipMapLODBias[TEXSTAGE_0] =
|
|
pow4( pContext->TextureStageState[TEXSTAGE_0].
|
|
m_fVal[D3DTSS_MIPMAPLODBIAS] );
|
|
|
|
pContext->MipMapLODBias[TEXSTAGE_1] =
|
|
pow4( pContext->TextureStageState[TEXSTAGE_1].
|
|
m_fVal[D3DTSS_MIPMAPLODBIAS] );
|
|
|
|
if ( pTexture0 != NULL )
|
|
{
|
|
__TXT_SetupTexture ( pThisDisplay,
|
|
0,
|
|
pContext->iTexStage[0],
|
|
pContext,
|
|
pTexture0,
|
|
pSoftP3RX,
|
|
bBothTexturesValid,
|
|
&mipBases);
|
|
}
|
|
|
|
if ( pTexture1 != NULL )
|
|
{
|
|
__TXT_SetupTexture ( pThisDisplay,
|
|
1,
|
|
pContext->iTexStage[1],
|
|
pContext,
|
|
pTexture1,
|
|
pSoftP3RX,
|
|
bBothTexturesValid,
|
|
&mipBases);
|
|
|
|
#if DX7_PALETTETEXTURE
|
|
if (GET_BLEND_ERROR(pContext) == BSF_TOO_MANY_PALETTES)
|
|
{
|
|
if (pTexture0 &&
|
|
(pTexture0->dwPaletteHandle == pTexture1->dwPaletteHandle))
|
|
{
|
|
RESET_BLEND_ERROR(pContext);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// Fix up the D3DRENDERSTATE_MODULATE case.
|
|
if( pTexture0 != NULL )
|
|
{
|
|
if( pContext->Flags & SURFACE_MODULATE )
|
|
{
|
|
// If SURFACE_MODULATE is set then we must have seen a
|
|
// DX5-style texture blend
|
|
// Note : bAlpha is true for CI8 and CI4 textures
|
|
|
|
BOOL bSelectArg1 = pTexture0->pFormatSurface->bAlpha;
|
|
|
|
#if DX7_PALETTETEXTURE
|
|
if( pTexture0->pixFmt.dwFlags & DDPF_PALETTEINDEXED8 )
|
|
{
|
|
bSelectArg1 = pTexture0->dwPaletteFlags & DDRAWIPAL_ALPHA;
|
|
}
|
|
#endif
|
|
|
|
if( bSelectArg1 )
|
|
{
|
|
TSSTATE( pContext->iChipStage[0], D3DTSS_ALPHAOP ) =
|
|
D3DTOP_SELECTARG1;
|
|
}
|
|
else
|
|
{
|
|
TSSTATE( pContext->iChipStage[0], D3DTSS_ALPHAOP ) =
|
|
D3DTOP_SELECTARG2;
|
|
}
|
|
}
|
|
}
|
|
|
|
P3_DMA_GET_BUFFER();
|
|
|
|
// Textures set up - now do the blending.
|
|
|
|
// These might be overidden later for special blends.
|
|
dwTexAppTfactor = pContext->RenderStates[D3DRENDERSTATE_TEXTUREFACTOR];
|
|
dwTexComp0Tfactor = pContext->RenderStates[D3DRENDERSTATE_TEXTUREFACTOR];
|
|
dwTexComp1Tfactor = pContext->RenderStates[D3DRENDERSTATE_TEXTUREFACTOR];
|
|
|
|
// Detect the stage 0 & 1 bumpmap setup code.
|
|
if (( TSSTATE ( TEXSTAGE_0, D3DTSS_TEXTUREMAP ) != 0 ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_TEXTUREMAP ) != 0 ) &&
|
|
( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) != D3DTOP_DISABLE ) )
|
|
{
|
|
// Looking good for a bumpmap. Now find various special cases.
|
|
// First of all, do they want anything in the stage 2 current colour?
|
|
if (
|
|
( ( ( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG1 ) != D3DTA_CURRENT ) &&
|
|
( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG2 ) != D3DTA_CURRENT ) ) ||
|
|
( ( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG1 ) != D3DTA_CURRENT ) ) ||
|
|
( ( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) == D3DTOP_SELECTARG2 ) &&
|
|
( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG2 ) != D3DTA_CURRENT ) ) ) &&
|
|
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) != D3DTOP_DOTPRODUCT3 ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) != D3DTOP_DOTPRODUCT3 ) )
|
|
{
|
|
// Nope - they don't care what the current colour channel is, and
|
|
// no dotproducts are used in stages 0 and 1 (they affect the alpha
|
|
// channel) so ignore what is in the colour channel - this is a
|
|
// bumpmap so far.
|
|
|
|
// Now see if they want a bumpmap or an inverted bumpmap. People
|
|
// are so fussy.
|
|
|
|
// Check first stage.
|
|
if (( ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) ) ||
|
|
( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) ) ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) )
|
|
{
|
|
// First stage fine and not inverted. Check second stage.
|
|
if (( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) ||
|
|
( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) )
|
|
{
|
|
// Fine, not inverted.
|
|
pContext->bBumpmapEnabled = TRUE;
|
|
pContext->bBumpmapInverted = FALSE;
|
|
}
|
|
else if (
|
|
( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) ) ||
|
|
( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) ) )
|
|
{
|
|
// Fine, inverted.
|
|
pContext->bBumpmapEnabled = TRUE;
|
|
pContext->bBumpmapInverted = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Nope, second stage is no good.
|
|
pContext->bBumpmapEnabled = FALSE;
|
|
pContext->bBumpmapInverted = FALSE;
|
|
}
|
|
}
|
|
else if (
|
|
( ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == (D3DTA_TEXTURE | D3DTA_COMPLEMENT) ) ) ||
|
|
( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG2 ) == (D3DTA_TEXTURE | D3DTA_COMPLEMENT) ) ) ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) )
|
|
{
|
|
// First stage fine and inverted. Check second stage.
|
|
if (( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) ||
|
|
( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) )
|
|
{
|
|
// Fine, inverted.
|
|
pContext->bBumpmapEnabled = TRUE;
|
|
pContext->bBumpmapInverted = TRUE;
|
|
}
|
|
else if (
|
|
( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) ) ||
|
|
( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
|
|
( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) ) )
|
|
{
|
|
// Fine, not inverted.
|
|
pContext->bBumpmapEnabled = TRUE;
|
|
pContext->bBumpmapInverted = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// Nope, second stage is no good.
|
|
pContext->bBumpmapEnabled = FALSE;
|
|
pContext->bBumpmapInverted = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Nope, first stage is no good.
|
|
pContext->bBumpmapEnabled = FALSE;
|
|
pContext->bBumpmapInverted = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Could do some more checking, e.g. is all they want in the current colour
|
|
// channel easily available from a single input, e.g. tex0.c, in which case
|
|
// that's fine. A non-bumpmap variant also needs to sense that the first
|
|
// stage is simply a selectarg1/2 and thus can ignore the first stage as
|
|
// a texcomp stage.
|
|
// But that's for later.
|
|
pContext->bBumpmapEnabled = FALSE;
|
|
pContext->bBumpmapInverted = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
pContext->bBumpmapEnabled = FALSE;
|
|
pContext->bBumpmapInverted = FALSE;
|
|
}
|
|
|
|
if ( pContext->bBumpmapEnabled )
|
|
{
|
|
DISPDBG((DBGLVL,"Enabling emboss bumpmapping"));
|
|
// Remap stages 1 & 2 out of existence.
|
|
pContext->iChipStage[0] = TEXSTAGE_2;
|
|
pContext->iChipStage[1] = TEXSTAGE_3;
|
|
pContext->iChipStage[2] = TEXSTAGE_4;
|
|
pContext->iChipStage[3] = TEXSTAGE_5;
|
|
}
|
|
else
|
|
{
|
|
// Normal mapping.
|
|
pContext->iChipStage[0] = TEXSTAGE_0;
|
|
pContext->iChipStage[1] = TEXSTAGE_1;
|
|
pContext->iChipStage[2] = TEXSTAGE_2;
|
|
pContext->iChipStage[3] = TEXSTAGE_3;
|
|
}
|
|
|
|
iLastChipStage = 0;
|
|
// Set these flags to FALSE as the stages are processed.
|
|
bProcessChipStage0 = TRUE;
|
|
bProcessChipStage1 = TRUE;
|
|
bProcessChipStage2 = TRUE;
|
|
|
|
// Turn on the basic enables.
|
|
pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_ENABLE;
|
|
// pSoftP3RX->P3RXTextureApplicationMode.EnableKs = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureApplicationMode.EnableKd = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureApplicationMode.MotionCompEnable = __PERMEDIA_DISABLE;
|
|
|
|
|
|
// Handle chip stage 0.
|
|
|
|
// Detect the very special-case glossmap+bumpmap code. There is no easy way
|
|
// to generalise it, so the whole chunk gets checked here.
|
|
if ( bProcessChipStage0 && bProcessChipStage1 && bProcessChipStage2 && pContext->bTex0Valid && pContext->bTex1Valid &&
|
|
// Colour channel of stage 0 can be whatever you want.
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) == D3DTOP_MODULATEALPHA_ADDCOLOR ) && // Early-out test - nothing uses this!
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == D3DTA_DIFFUSE ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( TEXSTAGE_2, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
|
|
( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( TEXSTAGE_3, D3DTSS_COLOROP ) == D3DTOP_MODULATE2X ) &&
|
|
( TSSTATE ( TEXSTAGE_3, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( TEXSTAGE_3, D3DTSS_COLORARG2 ) == (D3DTA_CURRENT | D3DTA_ALPHAREPLICATE) ) &&
|
|
( TSSTATE ( TEXSTAGE_3, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( TEXSTAGE_3, D3DTSS_ALPHAARG1 ) == D3DTA_TFACTOR ) &&
|
|
( TSSTATE ( TEXSTAGE_4, D3DTSS_COLOROP ) == D3DTOP_DISABLE ) &&
|
|
( pContext->iStageTex[0] == 0 ) &&
|
|
( pContext->iStageTex[1] == 1 ) &&
|
|
( pContext->iStageTex[2] == 0 )
|
|
)
|
|
{
|
|
int iMode;
|
|
// OK, looks good. Check which way round the bumpmapping is being done.
|
|
if (( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG2 ) == (D3DTA_CURRENT | D3DTA_COMPLEMENT) ) )
|
|
{
|
|
// Standard emboss.
|
|
iMode = 0;
|
|
}
|
|
else if (( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG1 ) == (D3DTA_TEXTURE | D3DTA_COMPLEMENT) ) &&
|
|
( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) )
|
|
{
|
|
// Inverted emboss.
|
|
iMode = 1;
|
|
}
|
|
else
|
|
{
|
|
// No good - can't do it.
|
|
iMode = -1;
|
|
}
|
|
|
|
if ( iMode == -1 )
|
|
{
|
|
// Nope.
|
|
SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_BLEND_STAGES );
|
|
bProcessChipStage0 = FALSE;
|
|
bProcessChipStage1 = FALSE;
|
|
bProcessChipStage2 = FALSE;
|
|
iLastChipStage = 3;
|
|
}
|
|
else
|
|
{
|
|
// Set up the colour channel of tc0.
|
|
// Alpha channel will be overridden later.
|
|
__TXT_TranslateToChipBlendMode(pContext,
|
|
&pContext->TextureStageState[0],
|
|
pSoftP3RX,
|
|
0,
|
|
0);
|
|
|
|
// Pass through bump.a, maybe inverted.
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_HEIGHTA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.I = P3RX_TEXCOMP_I_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.B = P3RX_TEXCOMP_ARG2;
|
|
if ( iMode )
|
|
{
|
|
// Inverted bumpmap.
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
// Non-inverted bumpmap.
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
}
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertI = __PERMEDIA_DISABLE;
|
|
|
|
// Do tex1.c * diff.a + current.c
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Arg1 = P3RX_TEXCOMP_T1C;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Arg2 = P3RX_TEXCOMP_OC;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.I = P3RX_TEXCOMP_I_CA;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.B = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.InvertI = __PERMEDIA_DISABLE;
|
|
|
|
// Pass through bump.a again.
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg1 = P3RX_TEXCOMP_OA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg2 = P3RX_TEXCOMP_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.I = P3RX_TEXCOMP_I_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.B = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertI = __PERMEDIA_DISABLE;
|
|
|
|
// Do current.c * current.a, by doing B*I+A. A=black, B=current.c, I=current.a
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorA = P3RX_TEXAPP_A_KC;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorB = P3RX_TEXAPP_B_TC;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorI = P3RX_TEXAPP_I_TA;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorInvertI = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorOperation = P3RX_TEXAPP_OPERATION_MODULATE_BI_ADD_A;
|
|
// Set the colour channel to black (allow the alpha channel to be preserved).
|
|
dwTexAppTfactor &= 0xff000000;
|
|
|
|
// Alpha channel selects the constant color.
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaA = P3RX_TEXAPP_A_KA;
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaB = P3RX_TEXAPP_B_KA;
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaInvertI = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaOperation = P3RX_TEXAPP_OPERATION_PASS_B;
|
|
|
|
// Do *2 in alpha-blend unit.
|
|
bAlphaBlendDouble = TRUE;
|
|
|
|
// We don't actually need the remap (and it doesn't mean much),
|
|
// but it stops erroneous errors being flagged.
|
|
pContext->iChipStage[0] = TEXSTAGE_0;
|
|
pContext->iChipStage[1] = TEXSTAGE_1;
|
|
pContext->iChipStage[2] = TEXSTAGE_3;
|
|
pContext->iChipStage[3] = TEXSTAGE_4;
|
|
|
|
bProcessChipStage0 = FALSE;
|
|
bProcessChipStage1 = FALSE;
|
|
bProcessChipStage2 = FALSE;
|
|
iLastChipStage = 3;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Detect the special-case 3-blend-unit bumpmapping mode.
|
|
// Third stage will be set up by the standard routines - only the first
|
|
// two are special-cased and shoehorned into TexComp0.
|
|
if ( bProcessChipStage0 && !pContext->bBumpmapEnabled && pContext->bTex0Valid && pContext->bTex1Valid &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_MODULATE ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG2 ) == D3DTA_DIFFUSE ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
|
|
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
|
|
// ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAARG2 ) == D3DTA_DIFFUSE ) dont care &&
|
|
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
|
|
(
|
|
( ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) ||
|
|
( ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) )
|
|
) )
|
|
{
|
|
// Yep, looks good. Set it up.
|
|
ASSERTDD ( pContext->iTexStage[0] == 0, "** _D3DChangeTextureP3RX: textures not correct for special bumpmapping" );
|
|
ASSERTDD ( pContext->iTexStage[1] == 1, "** _D3DChangeTextureP3RX: textures not correct for special bumpmapping" );
|
|
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_T0C;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_CC;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.I = P3RX_TEXCOMP_I_CA;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.B = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_DISABLE;
|
|
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_HEIGHTA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.I = P3RX_TEXCOMP_I_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.B = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertI = __PERMEDIA_DISABLE;
|
|
|
|
if ( ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
|
|
( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) )
|
|
{
|
|
// Inverted bumpmap.
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
// Normal bumpmap.
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
}
|
|
|
|
// Done chip stage 0, TSS stage 0 & 1. Move chip stage 1 on a notch.
|
|
pContext->iChipStage[0] = TEXSTAGE_0;
|
|
pContext->iChipStage[1] = TEXSTAGE_2;
|
|
pContext->iChipStage[2] = TEXSTAGE_3;
|
|
pContext->iChipStage[3] = TEXSTAGE_4;
|
|
iLastChipStage = 1;
|
|
bProcessChipStage0 = FALSE;
|
|
}
|
|
|
|
// Detect a chipstage 0 MODULATE+ADD concatenation. Used by lightmaps.
|
|
// This compresses two stages into texcomp0. The alpha channel has
|
|
// two modes - either one of the two stages just does a selectarg1 (current),
|
|
// and the other gets set up as normal, or (for specular stuff) they
|
|
// both do ADDSIGNED (cur, cur), in which case it's special-cased.
|
|
if ( bProcessChipStage0 && pContext->bBumpmapEnabled &&
|
|
( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) == D3DTOP_MODULATE ) &&
|
|
( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLORARG1 ) == ( D3DTA_CURRENT | D3DTA_ALPHAREPLICATE ) ) &&
|
|
( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLORARG2 ) == D3DTA_DIFFUSE ) &&
|
|
( ( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_ADD ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) ) ||
|
|
( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) ) ) )
|
|
{
|
|
// Colour channel is correct and can be squashed down to one stage.
|
|
// Check that the alpha channel is OK.
|
|
int bOK;
|
|
if (( ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) ||
|
|
( ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
|
|
( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) )
|
|
{
|
|
// Stage 0 is set to pass-through - set up texcomp0 as stage 1.
|
|
// Colour channel will be overridden later.
|
|
__TXT_TranslateToChipBlendMode(pContext,
|
|
&pContext->TextureStageState[pContext->iChipStage[1]],
|
|
pSoftP3RX,
|
|
pContext->iChipStage[1],
|
|
0);
|
|
bOK = TRUE;
|
|
}
|
|
else if (( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) ||
|
|
( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) )
|
|
{
|
|
// Stage 1 is set to pass-through - set up texcomp0 as stage 0.
|
|
// Colour channel will be overridden later.
|
|
__TXT_TranslateToChipBlendMode(pContext,
|
|
&pContext->TextureStageState[pContext->iChipStage[0]],
|
|
pSoftP3RX,
|
|
pContext->iChipStage[0],
|
|
0);
|
|
bOK = TRUE;
|
|
}
|
|
else if (( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
|
|
( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) &&
|
|
( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) )
|
|
{
|
|
// Set up to do ( 4 * cur.a - 1.5 ), or rather 4 * ( cur.a - 0.375 )
|
|
dwTexComp0Tfactor = 0x60606060; // All channels set to (0.375)
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_SUBTRACT_AB;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_FOUR;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_HEIGHTA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_FA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.I = P3RX_TEXCOMP_I_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.B = P3RX_TEXCOMP_ARG2;
|
|
if ( pContext->bBumpmapInverted )
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
}
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertI = __PERMEDIA_DISABLE;
|
|
bOK = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bOK = FALSE;
|
|
}
|
|
|
|
if ( bOK )
|
|
{
|
|
// OK, the alpha channel is fine - set up the colour channel now.
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
|
|
if ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_ADD )
|
|
{
|
|
// Yes, this is the ((diff.c*cur.a)+tex.c) case.
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_CC;
|
|
if ( pContext->iStageTex[pContext->iChipStage[1]] == 0 )
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_T0C;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_T1C;
|
|
}
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.I = P3RX_TEXCOMP_I_HA;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.B = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
|
|
if ( pContext->bBumpmapInverted )
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_DISABLE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Yes, this is just the (diff.c*cur.a) case.
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_CC;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_HEIGHTA;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.I = P3RX_TEXCOMP_I_OA;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.B = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
|
|
if ( pContext->bBumpmapInverted )
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_DISABLE;
|
|
}
|
|
}
|
|
|
|
// Done chip stage 0, TSS stage 0 & 1. Move chip stage 1 on a notch.
|
|
pContext->iChipStage[1]++;
|
|
pContext->iChipStage[2]++;
|
|
pContext->iChipStage[3]++;
|
|
iLastChipStage = 1;
|
|
bProcessChipStage0 = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
if ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) == D3DTOP_DISABLE )
|
|
{
|
|
// Nothing more to do.
|
|
bProcessChipStage0 = FALSE;
|
|
bProcessChipStage1 = FALSE;
|
|
bProcessChipStage2 = FALSE;
|
|
}
|
|
|
|
if ( pContext->iStageTex[pContext->iChipStage[0]] == -1 )
|
|
{
|
|
// This stage has no texture - is anyone trying to use it?
|
|
if (( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG2 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG1 ) )
|
|
{
|
|
// Panic! In future, we should feed white to the argument using the TFACTOR thing,
|
|
// but for now just disable the rest of the pipeline.
|
|
bProcessChipStage0 = FALSE;
|
|
bProcessChipStage1 = FALSE;
|
|
bProcessChipStage2 = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( bProcessChipStage0 )
|
|
{
|
|
// Set up stage 0
|
|
DISPDBG((DBGLVL,"Texture Stage 0 is valid - setting it up"));
|
|
__TXT_TranslateToChipBlendMode(pContext,
|
|
&pContext->TextureStageState[pContext->iChipStage[0]],
|
|
pSoftP3RX,
|
|
pContext->iChipStage[0],
|
|
0);
|
|
iLastChipStage = 1;
|
|
bProcessChipStage0 = FALSE;
|
|
}
|
|
|
|
|
|
// Handle chip stage 1.
|
|
|
|
|
|
if ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_DISABLE )
|
|
{
|
|
// Nothing more to do.
|
|
bProcessChipStage1 = FALSE;
|
|
bProcessChipStage2 = FALSE;
|
|
}
|
|
|
|
if ( pContext->iStageTex[pContext->iChipStage[1]] == -1 )
|
|
{
|
|
// This stage has no texture - is anyone trying to use it?
|
|
if (( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG2 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG1 ) )
|
|
{
|
|
// Panic! In future, we should feed white to the argument using the TFACTOR thing,
|
|
// but for now just disable the rest of the pipeline.
|
|
bProcessChipStage1 = FALSE;
|
|
bProcessChipStage2 = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
if ( bProcessChipStage1 )
|
|
{
|
|
// Set up stage 1
|
|
DISPDBG((DBGLVL,"Texture Stage 1 is valid - setting it up"));
|
|
__TXT_TranslateToChipBlendMode(pContext,
|
|
&pContext->TextureStageState[pContext->iChipStage[1]],
|
|
pSoftP3RX,
|
|
pContext->iChipStage[1],
|
|
1);
|
|
|
|
iLastChipStage = 2;
|
|
bProcessChipStage1 = FALSE;
|
|
}
|
|
|
|
|
|
|
|
// Handle chip stage 2.
|
|
|
|
|
|
if ( TSSTATE ( pContext->iChipStage[2], D3DTSS_COLOROP ) == D3DTOP_DISABLE )
|
|
{
|
|
// Nothing more to do.
|
|
bProcessChipStage2 = FALSE;
|
|
}
|
|
|
|
if ( pContext->iStageTex[pContext->iChipStage[2]] == -1 )
|
|
{
|
|
// This stage has no texture - is anyone trying to use it?
|
|
if (( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG2 ) ||
|
|
( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG1 ) )
|
|
{
|
|
// Panic! In future, we should feed white to the argument using the TFACTOR thing,
|
|
// but for now just disable the rest of the pipeline.
|
|
bProcessChipStage2 = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( bProcessChipStage2 )
|
|
{
|
|
// Set up chip stage 2 - texapp.
|
|
DISPDBG((DBGLVL,"Texture Stage 2 is valid - setting it up"));
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: Cool - an app is using the "
|
|
"TexApp unit - tell someone!"));
|
|
__TXT_TranslateToChipBlendMode(pContext,
|
|
&pContext->TextureStageState[pContext->iChipStage[2]],
|
|
pSoftP3RX,
|
|
pContext->iChipStage[2],
|
|
2);
|
|
iLastChipStage = 3;
|
|
bProcessChipStage2 = FALSE;
|
|
}
|
|
|
|
// This must be last.
|
|
if ( TSSTATE ( pContext->iChipStage[3], D3DTSS_COLOROP ) != D3DTOP_DISABLE )
|
|
{
|
|
// Oops - ran out of stages to set up.
|
|
SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_BLEND_STAGES );
|
|
iLastChipStage = 3;
|
|
}
|
|
|
|
switch ( iLastChipStage )
|
|
{
|
|
case 0:
|
|
DISPDBG((DBGLVL,"Texture Composite 0 is disabled"));
|
|
// This should have been caught ages ago.
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_CC;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
|
|
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_CA;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
|
|
// fall through
|
|
case 1:
|
|
DISPDBG((DBGLVL,"Texture Composite 1 is disabled"));
|
|
// Make sure the second stage passes the texel that the first stage generated
|
|
if ( pContext->bStage0DotProduct )
|
|
{
|
|
// First stage was a dot-product - do the summing (even in the alpha channel).
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Arg2 = P3RX_TEXCOMP_SUM;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg2 = P3RX_TEXCOMP_SUM;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Arg2 = P3RX_TEXCOMP_OC;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg2 = P3RX_TEXCOMP_OA;
|
|
}
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.A = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeColorMode1.Enable = __PERMEDIA_ENABLE;
|
|
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertArg2 = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.A = P3RX_TEXCOMP_ARG2;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
|
|
pSoftP3RX->P3RXTextureCompositeAlphaMode1.Enable = __PERMEDIA_ENABLE;
|
|
// fall through
|
|
case 2:
|
|
// Texapp to passthrough.
|
|
DISPDBG((DBGLVL,"Texture Application is disabled"));
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorB = P3RX_TEXAPP_B_TC;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorOperation = P3RX_TEXAPP_OPERATION_PASS_B;
|
|
pSoftP3RX->P3RXTextureApplicationMode.ColorInvertI = __PERMEDIA_DISABLE;
|
|
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaB = P3RX_TEXAPP_B_TC;
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaOperation = P3RX_TEXAPP_OPERATION_PASS_B;
|
|
pSoftP3RX->P3RXTextureApplicationMode.AlphaInvertI = __PERMEDIA_DISABLE;
|
|
// fall through
|
|
case 3:
|
|
// Nothing else in the pipeline to disable.
|
|
// fall through
|
|
break;
|
|
default:
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: iLastChipStage was > 3 - oops."));
|
|
break;
|
|
}
|
|
|
|
|
|
// Set up the alpha-map filtering to reflect the single/multi/mip-mapped texturing status
|
|
// All the other colour-key stuff has already been set up.
|
|
if( pContext->bCanChromaKey )
|
|
{
|
|
ASSERTDD ( pTexture0 != NULL, "** _D3DChangeTextureP3RX: pTexture was NULL" );
|
|
if( pTexture0->bMipMap )
|
|
{
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit0 = 4;
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit1 = 4;
|
|
if ( pContext->bTex0Valid )
|
|
{
|
|
// Filter mode is irrelevant - this just works!
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit01 = 7;
|
|
}
|
|
else
|
|
{
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: Trying to mipmap without a valid texture."));
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit01 = 8;
|
|
}
|
|
ASSERTDD ( !pContext->bTex1Valid, "** _D3DChangeTextureP3RX: Trying to mipmap with too many textures." );
|
|
}
|
|
else
|
|
{
|
|
// No mipmapping.
|
|
if ( pContext->bTex0Valid )
|
|
{
|
|
// Don't care about filter mode - this just works.
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit0 = 7;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit0 = 4;
|
|
}
|
|
if ( pContext->bTex1Valid )
|
|
{
|
|
// Don't care about filter mode - this just works.
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit1 = 7;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit1 = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Enable Texture Address calculation
|
|
pSoftP3RX->P3RXTextureCoordMode.Enable = __PERMEDIA_ENABLE;
|
|
|
|
// Enable filtering
|
|
pSoftP3RX->P3RXTextureFilterMode.Enable = __PERMEDIA_ENABLE;
|
|
|
|
// // Enable Texel color generation
|
|
// pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_ENABLE;
|
|
|
|
// Do we need to share the texture coordinates ?
|
|
if ( pContext->bTex0Valid && pContext->bTex1Valid &&
|
|
( TSSTATE ( pContext->iTexStage[0], D3DTSS_TEXCOORDINDEX ) ==
|
|
TSSTATE ( pContext->iTexStage[1], D3DTSS_TEXCOORDINDEX ) ) )
|
|
{
|
|
pSoftP3RX->P3RX_P3DeltaControl.ShareS = __PERMEDIA_ENABLE;
|
|
pSoftP3RX->P3RX_P3DeltaControl.ShareT = __PERMEDIA_ENABLE;
|
|
}
|
|
else
|
|
{
|
|
pSoftP3RX->P3RX_P3DeltaControl.ShareS = __PERMEDIA_DISABLE;
|
|
pSoftP3RX->P3RX_P3DeltaControl.ShareT = __PERMEDIA_DISABLE;
|
|
}
|
|
|
|
P3_ENSURE_DX_SPACE((P3_LOD_LEVELS*2));
|
|
WAIT_FIFO((P3_LOD_LEVELS*2));
|
|
for (i = 0; i < P3_LOD_LEVELS; i++)
|
|
{
|
|
COPY_P3_DATA_OFFSET(TextureMapWidth0, pSoftP3RX->P3RXTextureMapWidth[i], i);
|
|
}
|
|
|
|
if ( ( GET_BLEND_ERROR(pContext) & BLEND_STATUS_FATAL_FLAG ) != 0 )
|
|
{
|
|
// Got a fatal blend error - signal it to the user.
|
|
|
|
DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: invalid blend mode"));
|
|
|
|
_D3DDisplayWholeTSSPipe ( pContext, WRNLVL );
|
|
|
|
// And make sure this is re-evaluated next time we render,
|
|
// so that this (probably very munged) invalid setup doesn't cripple
|
|
// any subsequent valid renderstates.
|
|
DIRTY_EVERYTHING(pContext);
|
|
}
|
|
|
|
|
|
P3_ENSURE_DX_SPACE(32);
|
|
WAIT_FIFO(32);
|
|
SEND_P3_DATA(TextureCompositeMode, __PERMEDIA_ENABLE);
|
|
COPY_P3_DATA(TextureFilterMode, pSoftP3RX->P3RXTextureFilterMode);
|
|
|
|
COPY_P3_DATA(TextureApplicationMode, pSoftP3RX->P3RXTextureApplicationMode);
|
|
COPY_P3_DATA(TextureCoordMode, pSoftP3RX->P3RXTextureCoordMode);
|
|
COPY_P3_DATA(DeltaControl, pSoftP3RX->P3RX_P3DeltaControl);
|
|
|
|
// Copy the current TFACTOR values.
|
|
SEND_P3_DATA ( TextureEnvColor, FORMAT_8888_32BIT_BGR(dwTexAppTfactor) );
|
|
SEND_P3_DATA ( TextureCompositeFactor0, FORMAT_8888_32BIT_BGR(dwTexComp0Tfactor) );
|
|
SEND_P3_DATA ( TextureCompositeFactor1, FORMAT_8888_32BIT_BGR(dwTexComp1Tfactor) );
|
|
DISPDBG((DBGLVL,"Current TFACTOR values. %x %x %x",
|
|
dwTexAppTfactor,
|
|
dwTexComp0Tfactor,
|
|
dwTexComp1Tfactor));
|
|
|
|
COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
|
|
|
|
P3_ENSURE_DX_SPACE(32);
|
|
WAIT_FIFO(32);
|
|
|
|
COPY_P3_DATA(TextureCompositeColorMode0, pSoftP3RX->P3RXTextureCompositeColorMode0);
|
|
COPY_P3_DATA(TextureCompositeColorMode1, pSoftP3RX->P3RXTextureCompositeColorMode1);
|
|
COPY_P3_DATA(TextureCompositeAlphaMode0, pSoftP3RX->P3RXTextureCompositeAlphaMode0);
|
|
COPY_P3_DATA(TextureCompositeAlphaMode1, pSoftP3RX->P3RXTextureCompositeAlphaMode1);
|
|
|
|
COPY_P3_DATA(TextureReadMode1, pSoftP3RX->P3RXTextureReadMode1);
|
|
COPY_P3_DATA(TextureIndexMode1, pSoftP3RX->P3RXTextureIndexMode1);
|
|
|
|
COPY_P3_DATA(TextureReadMode0, pSoftP3RX->P3RXTextureReadMode0);
|
|
COPY_P3_DATA(TextureIndexMode0, pSoftP3RX->P3RXTextureIndexMode0);
|
|
|
|
// Make sure the texture cache is invalidated
|
|
P3RX_INVALIDATECACHE(__PERMEDIA_ENABLE, __PERMEDIA_DISABLE);
|
|
|
|
SEND_P3_DATA(LOD, 0);
|
|
SEND_P3_DATA(LOD1, 0);
|
|
|
|
{
|
|
struct LodRange range;
|
|
|
|
// Clear down whole register
|
|
|
|
*(DWORD *)&range = 0;
|
|
|
|
// Each of the Min and Max LODs are in 4.8 format. We only deal
|
|
// with integer LODs in the range (0, N) so we just compute the
|
|
// upper value N and shift it up 8 bits.
|
|
|
|
range.Min = 0;
|
|
range.Max = ( mipBases.dwTex0MipMax - mipBases.dwTex0MipBase ) << 8;
|
|
COPY_P3_DATA( LodRange0, range );
|
|
|
|
range.Min = 0;
|
|
range.Max = ( mipBases.dwTex1MipMax - mipBases.dwTex1MipBase ) << 8;
|
|
COPY_P3_DATA( LodRange1, range );
|
|
}
|
|
|
|
*pFlags |= SURFACE_TEXTURING;
|
|
|
|
// Turn texturing on in the render command
|
|
RENDER_TEXTURE_ENABLE(pContext->RenderCommand);
|
|
|
|
P3_DMA_COMMIT_BUFFER();
|
|
|
|
// See if the alpha-blend unit needs to be updated.
|
|
if ( bAlphaBlendDouble != pContext->bAlphaBlendMustDoubleSourceColour )
|
|
{
|
|
pContext->bAlphaBlendMustDoubleSourceColour = bAlphaBlendDouble;
|
|
DIRTY_ALPHABLEND(pContext);
|
|
}
|
|
|
|
DBG_EXIT(_D3DChangeTextureP3RX,0);
|
|
|
|
} // _D3DChangeTextureP3RX
|
|
|