Leaked source code of windows server 2003
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

/******************************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