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.
 
 
 
 
 
 

2609 lines
110 KiB

/******************************Module*Header**********************************\
*
* *******************
* * D3D SAMPLE CODE *
* *******************
*
* Module Name: d3dstate.c
*
* Content: D3D renderstates and texture stage states translation
* into hardware specific settings.
*
* 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 "tag.h"
//-----------------------------Public Routine----------------------------------
//
// D3DGetDriverState
//
// This callback is used by both the DirectDraw and Direct3D runtimes to obtain
// information from the driver about its current state.
// NOTE: We need to hook up this callback even if we don't do anything in it
//
// Parameter
//
// pgdsd
// Pointer to a DD_GETDRIVERSTATEDATA structure.
//
// .dwFlags
// Flags to indicate the data requested.
// .lpDD
// Pointer to a DD_DIRECTDRAW_GLOBAL structure describing the device.
// .dwhContext
// Specifies the ID of the context for which information is being
// requested.
// .lpdwStates
// Pointer to the Direct3D driver state data to be filled in by the
// driver.
// .dwLength
// Specifies the length of the state data to be filled in by the
// driver.
// .ddRVal
// Specifies the return value.
//
//
// Note: If you're driver doesn't implement this callback it won't be
// recognized as a DX7 level driver
//-----------------------------------------------------------------------------
DWORD CALLBACK
D3DGetDriverState(
LPDDHAL_GETDRIVERSTATEDATA pgdsd)
{
P3_D3DCONTEXT* pContext;
DBG_CB_ENTRY(D3DGetDriverState);
#if DX7_TEXMANAGEMENT_STATS
if (pgdsd->dwFlags == D3DDEVINFOID_TEXTUREMANAGER)
{
if (pgdsd->dwLength < sizeof(D3DDEVINFO_TEXTUREMANAGER))
{
DISPDBG((ERRLVL,"D3DGetDriverState dwLength=%d is not sufficient",
pgdsd->dwLength));
return DDHAL_DRIVER_NOTHANDLED;
}
pContext = _D3D_CTX_HandleToPtr(pgdsd->dwhContext);
// Check if we got a valid context handle.
if (!CHECK_D3DCONTEXT_VALIDITY(pContext))
{
pgdsd->ddRVal = D3DHAL_CONTEXT_BAD;
DISPDBG((ERRLVL,"ERROR: Context not valid"));
DBG_CB_EXIT(D3DGetDriverState, D3DHAL_CONTEXT_BAD);
return (DDHAL_DRIVER_HANDLED);
}
// As the state buffer area lives in user memory, we need to
// access it bracketing it with a try/except block. This
// is because the user memory might under some circumstances
// become invalid while the driver is running and then it
// would AV. Also, the driver might need to do some cleanup
// before returning to the OS.
__try
{
_D3D_TM_STAT_GetStats(pContext,
(LPD3DDEVINFO_TEXTUREMANAGER)pgdsd->lpdwStates);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// On this driver we don't need to do anything special
DISPDBG((ERRLVL,"Driver caused exception at "
"line %u of file %s",
__LINE__,__FILE__));
pgdsd->ddRVal = DDERR_GENERIC;
DBG_CB_EXIT(D3DGetDriverState,0);
return DDHAL_DRIVER_NOTHANDLED;
}
pgdsd->ddRVal = DD_OK;
DBG_CB_EXIT(D3DGetDriverState,0);
return DDHAL_DRIVER_HANDLED;
}
#endif // DX7_TEXMANAGEMENT_STATS
// Fall trough for any unhandled DEVICEINFOID's
DISPDBG((ERRLVL,"D3DGetDriverState DEVICEINFOID=%08lx not supported",
pgdsd->dwFlags));
pgdsd->ddRVal = DDERR_UNSUPPORTED;
DBG_CB_EXIT(D3DGetDriverState,0);
return DDHAL_DRIVER_NOTHANDLED;
} // D3DGetDriverState
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
//-----------------------------------------------------------------------------
//
// _D3D_ST_CanRenderAntialiased
//
// Called when the D3DRENDERSTATE_ANTIALIAS RS is set to TRUE.
//
//-----------------------------------------------------------------------------
BOOL
_D3D_ST_CanRenderAntialiased(
P3_D3DCONTEXT* pContext,
BOOL bNewAliasBuffer)
{
P3_SOFTWARECOPY* pSoftPermedia = &pContext->SoftCopyGlint;
P3_THUNKEDDATA *pThisDisplay = pContext->pThisDisplay;
P3_MEMREQUEST mmrq;
DWORD dwResult;
P3_DMA_DEFS();
#if DX8_MULTISAMPLING
// Only 4 multisampling is supported
// And DX7 does not specifiy the number of samples.
if (pContext->pSurfRenderInt->dwSampling != 4)
{
return FALSE;
}
#endif // DX8_MULTISAMPLING
// Only allow AA rendering for 16-bit framebuffers with width and
// height no larger than 1024. The size restriction comes because
// later on we use the texture unit in order to shrink and filter
// the resulting rendertarget. Since the maximum texture size
// allowed in this hw is 2048, the maximum rendertarget we suppport
// with antialiasing is 1024.
if ((pContext->pSurfRenderInt->dwPixelSize != __GLINT_16BITPIXEL) ||
(pContext->pSurfRenderInt->wWidth > 1024) ||
(pContext->pSurfRenderInt->wHeight > 1024))
{
return FALSE;
}
// Do we need to release the current alias buffer
if (bNewAliasBuffer)
{
if (pContext->dwAliasBackBuffer != 0)
{
_DX_LIN_FreeLinearMemory(&pThisDisplay->LocalVideoHeap0Info,
pContext->dwAliasBackBuffer);
pContext->dwAliasBackBuffer = 0;
pContext->dwAliasPixelOffset = 0;
}
if (pContext->dwAliasZBuffer != 0)
{
_DX_LIN_FreeLinearMemory(&pThisDisplay->LocalVideoHeap0Info,
pContext->dwAliasZBuffer);
pContext->dwAliasZBuffer = 0;
pContext->dwAliasZPixelOffset = 0;
}
}
if ((pContext->pSurfRenderInt) && (! pContext->dwAliasBackBuffer))
{
// Allocate a 2x buffer if we need to
memset(&mmrq, 0, sizeof(P3_MEMREQUEST));
mmrq.dwSize = sizeof(P3_MEMREQUEST);
mmrq.dwBytes = pContext->pSurfRenderInt->lPitch * 2 *
pContext->pSurfRenderInt->wHeight * 2;
mmrq.dwAlign = 8;
mmrq.dwFlags = MEM3DL_FIRST_FIT;
mmrq.dwFlags |= MEM3DL_FRONT;
dwResult = _DX_LIN_AllocateLinearMemory(
&pThisDisplay->LocalVideoHeap0Info,
&mmrq);
// Did we get the memory we asked for?
if (dwResult != GLDD_SUCCESS)
{
return FALSE;
}
// Set up new backbuffer for antialiasing
pContext->dwAliasBackBuffer = mmrq.pMem;
pContext->dwAliasPixelOffset =
pContext->dwAliasBackBuffer -
pThisDisplay->dwScreenFlatAddr;
}
if ((pContext->pSurfZBufferInt) && (! pContext->dwAliasZBuffer))
{
memset(&mmrq, 0, sizeof(P3_MEMREQUEST));
mmrq.dwSize = sizeof(P3_MEMREQUEST);
mmrq.dwBytes = pContext->pSurfZBufferInt->lPitch * 2 *
pContext->pSurfZBufferInt->wHeight * 2;
mmrq.dwAlign = 8;
mmrq.dwFlags = MEM3DL_FIRST_FIT;
mmrq.dwFlags |= MEM3DL_FRONT;
dwResult = _DX_LIN_AllocateLinearMemory(
&pThisDisplay->LocalVideoHeap0Info,
&mmrq);
// Did we get the memory we asked for?
if (dwResult == GLDD_SUCCESS)
{
pContext->dwAliasZBuffer = mmrq.pMem;
pContext->dwAliasZPixelOffset =
pContext->dwAliasZBuffer
- pThisDisplay->dwScreenFlatAddr;
}
else
{
// Couldn't get the antialiasing memory for the backbuffer
if (pContext->dwAliasBackBuffer != 0)
{
_DX_LIN_FreeLinearMemory(
&pThisDisplay->LocalVideoHeap0Info,
pContext->dwAliasBackBuffer);
pContext->dwAliasBackBuffer = 0;
pContext->dwAliasPixelOffset = 0;
}
// No enough resource for antialisde rendering
return FALSE;
}
}
return TRUE;
} // _D3D_ST_CanRenderAntialiased
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
//-----------------------------------------------------------------------------
//
// __ST_HandleDirtyP3State
//
// Setup any pending hardware state necessary to correctly render our primitives
//
//-----------------------------------------------------------------------------
void
__ST_HandleDirtyP3State(
P3_THUNKEDDATA *pThisDisplay,
P3_D3DCONTEXT *pContext)
{
P3_SOFTWARECOPY* pSoftP3RX = &pContext->SoftCopyGlint;
P3_DMA_DEFS();
DISPDBG((DBGLVL,"Permedia context Dirtied, setting states:"));
// ********************************************************************
// NOTE: MAINTAIN STRICT ORDERING OF THESE EVALUATIONS FOR HW REASONS!!
// ********************************************************************
if (pContext->dwDirtyFlags == CONTEXT_DIRTY_EVERYTHING)
{
// Everything needs re-doing - re-set the blend status.
RESET_BLEND_ERROR(pContext);
}
//*********************************************************
// Has the z buffer/stencil buffer configuration changed ???
//*********************************************************
if ((pContext->dwDirtyFlags & CONTEXT_DIRTY_ZBUFFER) ||
(pContext->dwDirtyFlags & CONTEXT_DIRTY_STENCIL))
{
if ( ( (pContext->RenderStates[D3DRENDERSTATE_ZENABLE] == D3DZB_TRUE)
|| (pContext->RenderStates[D3DRENDERSTATE_ZENABLE] == D3DZB_USEW) )
&& (pContext->pSurfZBufferInt) )
{
// This includes W buffering as well as Z buffering.
// The actual W-specific stuff is set up later.
if (pContext->RenderStates[D3DRENDERSTATE_ZWRITEENABLE] == TRUE)
{
switch ((int)pSoftP3RX->P3RXDepthMode.CompareMode)
{
case __GLINT_DEPTH_COMPARE_MODE_ALWAYS:
// Although it seems as though the ReadDestination can be
// disabled, it can't. The result isn't correct because the
// chip does a compare on the current value as an optimization
// for updating the Z [CM].
// NOTE! The P3 can actually do the optimisation if you
// use some other flags. This needs fixing in the future.
DISPDBG((ERRLVL,"** __ST_HandleDirtyP3State: "
"please optimise the ZCMP_ALWAYS case"));
pSoftP3RX->P3RXLBWriteMode.WriteEnable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXLBDestReadMode.Enable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXDepthMode.WriteMask = __PERMEDIA_ENABLE;
break;
case __GLINT_DEPTH_COMPARE_MODE_NEVER:
pSoftP3RX->P3RXLBWriteMode.WriteEnable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXLBDestReadMode.Enable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXDepthMode.WriteMask = __PERMEDIA_DISABLE;
break;
default:
pSoftP3RX->P3RXLBWriteMode.WriteEnable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXLBDestReadMode.Enable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXDepthMode.WriteMask = __PERMEDIA_ENABLE;
break;
}
}
else
{
if ( ( pSoftP3RX->P3RXDepthMode.CompareMode == __GLINT_DEPTH_COMPARE_MODE_NEVER )
|| ( pSoftP3RX->P3RXDepthMode.CompareMode == __GLINT_DEPTH_COMPARE_MODE_ALWAYS ) )
{
pSoftP3RX->P3RXLBDestReadMode.Enable = __PERMEDIA_DISABLE;
}
else
{
pSoftP3RX->P3RXLBDestReadMode.Enable = __PERMEDIA_ENABLE;
}
pSoftP3RX->P3RXLBWriteMode.WriteEnable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXDepthMode.WriteMask = __PERMEDIA_DISABLE;
}
// Enable Z test
pSoftP3RX->P3RXDepthMode.Enable = __PERMEDIA_ENABLE;
}
else
{
// ** Not Z Buffering
// Disable Writes
pSoftP3RX->P3RXLBWriteMode.WriteEnable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXDepthMode.WriteMask = __PERMEDIA_DISABLE;
// Disable Z test
pSoftP3RX->P3RXDepthMode.Enable = __PERMEDIA_DISABLE;
// No reads
pSoftP3RX->P3RXLBDestReadMode.Enable = __PERMEDIA_DISABLE;
}
if (pContext->RenderStates[D3DRENDERSTATE_STENCILENABLE] != TRUE)
{
DISPDBG((DBGLVL,"Disabling Stencil"));
pSoftP3RX->P3RXStencilMode.Enable = __PERMEDIA_DISABLE;
}
else
{
DISPDBG((DBGLVL,"Enabling Stencil"));
pSoftP3RX->P3RXStencilMode.Enable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXLBDestReadMode.Enable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXLBWriteMode.WriteEnable = __PERMEDIA_ENABLE;
switch(pContext->RenderStates[D3DRENDERSTATE_STENCILFAIL])
{
case D3DSTENCILOP_KEEP:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_KEEP;
break;
case D3DSTENCILOP_ZERO:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_ZERO;
break;
case D3DSTENCILOP_REPLACE:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_REPLACE;
break;
case D3DSTENCILOP_INCR:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_INCR_WRAP;
break;
case D3DSTENCILOP_INCRSAT:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_INCR;
break;
case D3DSTENCILOP_DECR:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_DECR_WRAP;
break;
case D3DSTENCILOP_DECRSAT:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_DECR;
break;
case D3DSTENCILOP_INVERT:
pSoftP3RX->P3RXStencilMode.SFail = __GLINT_STENCIL_METHOD_INVERT;
break;
default:
DISPDBG((ERRLVL,"ERROR: Illegal D3DRENDERSTATE_STENCILFAIL!"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
switch(pContext->RenderStates[D3DRENDERSTATE_STENCILZFAIL])
{
case D3DSTENCILOP_KEEP:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_KEEP;
break;
case D3DSTENCILOP_ZERO:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_ZERO;
break;
case D3DSTENCILOP_REPLACE:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_REPLACE;
break;
case D3DSTENCILOP_INCR:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_INCR_WRAP;
break;
case D3DSTENCILOP_INCRSAT:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_INCR;
break;
case D3DSTENCILOP_DECR:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_DECR_WRAP;
break;
case D3DSTENCILOP_DECRSAT:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_DECR;
break;
case D3DSTENCILOP_INVERT:
pSoftP3RX->P3RXStencilMode.DPFail = __GLINT_STENCIL_METHOD_INVERT;
break;
default:
DISPDBG((ERRLVL,"ERROR: Illegal D3DRENDERSTATE_STENCILZFAIL!"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
switch(pContext->RenderStates[D3DRENDERSTATE_STENCILPASS])
{
case D3DSTENCILOP_KEEP:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_KEEP;
break;
case D3DSTENCILOP_ZERO:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_ZERO;
break;
case D3DSTENCILOP_REPLACE:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_REPLACE;
break;
case D3DSTENCILOP_INCR:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_INCR_WRAP;
break;
case D3DSTENCILOP_INCRSAT:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_INCR;
break;
case D3DSTENCILOP_DECR:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_DECR_WRAP;
break;
case D3DSTENCILOP_DECRSAT:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_DECR;
break;
case D3DSTENCILOP_INVERT:
pSoftP3RX->P3RXStencilMode.DPPass = __GLINT_STENCIL_METHOD_INVERT;
break;
default:
DISPDBG((ERRLVL,"ERROR: Illegal D3DRENDERSTATE_STENCILPASS!"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
switch (pContext->RenderStates[D3DRENDERSTATE_STENCILFUNC])
{
case D3DCMP_NEVER:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_NEVER;
break;
case D3DCMP_LESS:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_LESS;
break;
case D3DCMP_EQUAL:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_EQUAL;
break;
case D3DCMP_LESSEQUAL:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_LESS_OR_EQUAL;
break;
case D3DCMP_GREATER:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_GREATER;
break;
case D3DCMP_NOTEQUAL:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_NOT_EQUAL;
break;
case D3DCMP_GREATEREQUAL:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_GREATER_OR_EQUAL;
break;
case D3DCMP_ALWAYS:
pSoftP3RX->P3RXStencilMode.CompareFunction = __GLINT_STENCIL_COMPARE_MODE_ALWAYS;
break;
default:
DISPDBG((ERRLVL,"ERROR: Unknown D3DRENDERSTATE_STENCILFUNC!"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
pSoftP3RX->P3RXStencilData.StencilWriteMask = (pContext->RenderStates[D3DRENDERSTATE_STENCILWRITEMASK] & 0xFF);
pSoftP3RX->P3RXStencilData.CompareMask = (pContext->RenderStates[D3DRENDERSTATE_STENCILMASK] & 0xFF);
pSoftP3RX->P3RXStencilData.ReferenceValue = (pContext->RenderStates[D3DRENDERSTATE_STENCILREF] & 0xFF);
}
P3_DMA_GET_BUFFER();
P3_ENSURE_DX_SPACE(32);
WAIT_FIFO(32);
COPY_P3_DATA(DepthMode, pSoftP3RX->P3RXDepthMode);
COPY_P3_DATA(LBDestReadMode, pSoftP3RX->P3RXLBDestReadMode);
COPY_P3_DATA(LBWriteMode, pSoftP3RX->P3RXLBWriteMode);
COPY_P3_DATA(LBReadFormat, pSoftP3RX->P3RXLBReadFormat);
COPY_P3_DATA(LBWriteFormat, pSoftP3RX->P3RXLBWriteFormat);
COPY_P3_DATA(StencilData, pSoftP3RX->P3RXStencilData);
COPY_P3_DATA(StencilMode, pSoftP3RX->P3RXStencilMode);
P3_DMA_COMMIT_BUFFER();
}
//*********************************************************
// Has the alphatest type changed?
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_ALPHATEST)
{
DISPDBG((DBGLVL," Alpha testing"));
P3_DMA_GET_BUFFER();
P3_ENSURE_DX_SPACE(2);
WAIT_FIFO(2);
if (pContext->RenderStates[D3DRENDERSTATE_ALPHATESTENABLE] == FALSE)
{
pSoftP3RX->P3RXAlphaTestMode.Enable = __PERMEDIA_DISABLE;
DISPDBG((DBGLVL,"Alpha test disabled, ChromaTest = %d",
pContext->RenderStates[D3DRENDERSTATE_COLORKEYENABLE] ));
}
else
{
unsigned char ucChipAlphaRef;
DWORD dwAlphaRef;
if( pThisDisplay->dwDXVersion <= DX5_RUNTIME )
{
// Form 8 bit alpha reference value by scaling 1.16 fixed point to 0.8
dwAlphaRef = pContext->RenderStates[D3DRENDERSTATE_ALPHAREF];
// This conversion may need tweaking to cope with individual
// apps' expectations. Fortunately, it's DX5 only, so there
// are a finite number of them.
if ( dwAlphaRef == 0x0000 )
{
ucChipAlphaRef = 0x00;
}
else if ( dwAlphaRef < 0xfe00 )
{
// Add the inverted top char to the bottom char, so that
// the rounding changes smoothly all the way up to 0xfe00.
dwAlphaRef += ~( dwAlphaRef >> 8 );
ucChipAlphaRef = (unsigned char)( dwAlphaRef >> 8 );
}
else if ( dwAlphaRef < 0xffff )
{
// Clamp to make sure only 0xffff -> 0xff
ucChipAlphaRef = 0xfe;
}
else
{
ucChipAlphaRef = 0xff;
}
DISPDBG((DBGLVL,"Alpha test enabled: Value = 0x%x, ChipAlphaRef = 0x%x",
pContext->RenderStates[D3DRENDERSTATE_ALPHAREF],
ucChipAlphaRef ));
}
else
{
// ALPHAREF is an 8 bit value on input - just copy straight into the chip
dwAlphaRef = (unsigned char)pContext->RenderStates[D3DRENDERSTATE_ALPHAREF];
if ( dwAlphaRef > 0xff )
{
ucChipAlphaRef = 0xff;
}
else
{
ucChipAlphaRef = (unsigned char)dwAlphaRef;
}
DISPDBG((DBGLVL,"Alpha test enabled: AlphaRef = 0x%x", ucChipAlphaRef ));
}
pSoftP3RX->P3RXAlphaTestMode.Reference = ucChipAlphaRef;
pSoftP3RX->P3RXAlphaTestMode.Enable = __PERMEDIA_ENABLE;
switch (pContext->RenderStates[D3DRENDERSTATE_ALPHAFUNC])
{
case D3DCMP_GREATER:
DISPDBG((DBGLVL,"GREATER Alpha Test"));
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_GREATER;
break;
case D3DCMP_GREATEREQUAL:
DISPDBG((DBGLVL,"GREATEREQUAL Alpha Test"));
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_GREATER_OR_EQUAL;
break;
case D3DCMP_LESS:
DISPDBG((DBGLVL,"LESS Alpha Test"));
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_LESS;
break;
case D3DCMP_LESSEQUAL:
DISPDBG((DBGLVL,"LESSEQUAL Alpha Test"));
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_LESS_OR_EQUAL;
break;
case D3DCMP_NOTEQUAL:
DISPDBG((DBGLVL,"NOTEQUAL Alpha Test"));
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_NOT_EQUAL;
break;
case D3DCMP_EQUAL:
DISPDBG((DBGLVL,"EQUAL Alpha Test"));
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_EQUAL;
break;
case D3DCMP_NEVER:
DISPDBG((DBGLVL,"NEVER Alpha Test"));
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_NEVER;
break;
case D3DCMP_ALWAYS:
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_ALWAYS;
break;
default:
DISPDBG((ERRLVL,"Unsuported AlphaTest mode"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
}
COPY_P3_DATA(AlphaTestMode, pSoftP3RX->P3RXAlphaTestMode);
P3_DMA_COMMIT_BUFFER();
}
//*********************************************************
// Have the fogging parameters/state changed?
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_FOG)
{
if (!pContext->RenderStates[D3DRENDERSTATE_FOGENABLE])
{
pContext->Flags &= ~SURFACE_FOGENABLE;
pSoftP3RX->P3RXFogMode.Table = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXFogMode.UseZ = __PERMEDIA_DISABLE;
// Don't need delta to do fog value setup
pSoftP3RX->P3RX_P3DeltaMode.FogEnable = __PERMEDIA_DISABLE;
RENDER_FOG_DISABLE(pContext->RenderCommand);
}
else
{
DWORD CurrentEntry;
DWORD TableEntry;
float fEntry[256];
float FogStart;
float FogEnd;
float FogDensity;
LONG lWaitFifoEntries;
float fValue;
float z;
float zIncrement;
DWORD dwFogTableMode =
pContext->RenderStates[D3DRENDERSTATE_FOGTABLEMODE];
DWORD dwFogColor = pContext->RenderStates[D3DRENDERSTATE_FOGCOLOR];
// Enable fog in the render command
pContext->Flags |= SURFACE_FOGENABLE;
RENDER_FOG_ENABLE(pContext->RenderCommand);
DISPDBG((DBGLVL,"FogColor (BGR): 0x%x", dwFogColor));
P3_DMA_GET_BUFFER_ENTRIES(2)
SEND_P3_DATA(FogColor, RGBA_MAKE(RGBA_GETBLUE (dwFogColor),
RGBA_GETGREEN(dwFogColor),
RGBA_GETRED (dwFogColor),
RGBA_GETALPHA(dwFogColor)) );
P3_DMA_COMMIT_BUFFER();
pSoftP3RX->P3RXFogMode.ZShift = 23; // Take the top 8 bits of the z value
switch (dwFogTableMode)
{
case D3DFOG_NONE:
pSoftP3RX->P3RXFogMode.Table = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXFogMode.UseZ = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXFogMode.InvertFI = __PERMEDIA_DISABLE;
pSoftP3RX->P3RX_P3DeltaMode.FogEnable = __PERMEDIA_ENABLE;
break;
case D3DFOG_EXP:
case D3DFOG_EXP2:
case D3DFOG_LINEAR:
pSoftP3RX->P3RXFogMode.Table = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXFogMode.UseZ = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXFogMode.InvertFI = __PERMEDIA_DISABLE;
//pSoftP3RX->P3RX_P3DeltaMode.FogEnable = __PERMEDIA_DISABLE;
// Don't need delta to do fog value setup (z is used as fog lookup)
pSoftP3RX->P3RX_P3DeltaMode.FogEnable = __PERMEDIA_DISABLE;
FogStart = pContext->fRenderStates[D3DRENDERSTATE_FOGTABLESTART];
FogEnd = pContext->fRenderStates[D3DRENDERSTATE_FOGTABLEEND];
FogDensity = pContext->fRenderStates[D3DRENDERSTATE_FOGTABLEDENSITY];
DISPDBG((DBGLVL,"FogStart = %d FogEnd = %d FogDensity = %d",
(LONG)(FogStart*1000.0f),
(LONG)(FogEnd*1000.0f),
(LONG)(FogDensity*1000.0f) ));
// Compute the fog tables in order to load the hw fog tables
if (D3DFOG_LINEAR == dwFogTableMode)
{
TableEntry = 0;
zIncrement = 1.0f / 255.0f;
z = 0.0f;
do
{
// Linear fog, so clamp top and bottom
if (z < FogStart)
{
fValue = 1.0f;
}
else if (z > FogEnd)
{
fValue = 0.0f;
}
else
{
// If the end == the start, don't fog
if (FogEnd == FogStart)
{
fValue = 1.0f;
}
else
{
fValue = (FogEnd - z) / (FogEnd - FogStart);
}
ASSERTDD(fValue <= 1.0f,
"Error: Result to big");
ASSERTDD(fValue >= 0.0f,
"Error: Result negative");
}
// Scale the result to fill the
// 8 bit range in the table
fValue = fValue * 255.0f;
fEntry[TableEntry++] = fValue;
z += zIncrement;
} while (TableEntry < 256);
}
else if (D3DFOG_EXP == dwFogTableMode)
{
TableEntry = 0;
zIncrement = 1.0f / 255.0f;
z = 0.0f;
do
{
float fz;
fz = z * FogDensity;
fValue = myPow(math_e, -fz);
if (fValue <= 0.0f) fValue = 0.0f;
if (fValue > 1.0f) fValue = 1.0f;
// Scale the result to fill the
// 8 bit range in the table
fValue = fValue * 255.0f;
DISPDBG((DBGLVL,"Table Entry %d = %f, for Z = %f",
TableEntry, fValue, z));
fEntry[TableEntry++] = fValue;
z += zIncrement;
} while (TableEntry < 256);
}
else // must be if(D3DFOG_EXP2 == dwFogTableMode)
{
TableEntry = 0;
zIncrement = 1.0f / 255.0f;
z = 0.0f;
do
{
float fz;
fz = z * FogDensity;
fValue = myPow(math_e, -(fz * fz));
if (fValue <= 0.0f) fValue = 0.0f;
if (fValue > 1.0f) fValue = 1.0f;
// Scale the result to fill the
// 8 bit range in the table
fValue = fValue * 255.0f;
DISPDBG((DBGLVL,"Table Entry %d = %f, for Z = %f",
TableEntry, fValue, z));
fEntry[TableEntry++] = fValue;
z += zIncrement;
} while (TableEntry < 256);
}
P3_DMA_GET_BUFFER();
lWaitFifoEntries = 2;
// Pack the fog entries into the chip's fog table
CurrentEntry = 0;
for (TableEntry = 0; TableEntry < 256; TableEntry += 4)
{
DWORD Val[4];
DWORD dwValue;
myFtoi((int*)&Val[0], fEntry[TableEntry]);
myFtoi((int*)&Val[1], fEntry[TableEntry + 1]);
myFtoi((int*)&Val[2], fEntry[TableEntry + 2]);
myFtoi((int*)&Val[3], fEntry[TableEntry + 3]);
lWaitFifoEntries -= 2;
if (lWaitFifoEntries < 2)
{
P3_ENSURE_DX_SPACE(32);
WAIT_FIFO(32);
lWaitFifoEntries += 32;
}
dwValue = ((Val[0] ) |
(Val[1] << 8) |
(Val[2] << 16) |
(Val[3] << 24));
SEND_P3_DATA_OFFSET(FogTable0,
dwValue,
CurrentEntry++);
}
P3_DMA_COMMIT_BUFFER();
break;
default:
DISPDBG((ERRLVL,"ERROR: Unknown fog table mode!"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
} // switch (dwFogTableMode)
} // if (!pContext->RenderStates[D3DRENDERSTATE_FOGENABLE])
P3_DMA_GET_BUFFER_ENTRIES(6);
SEND_P3_DATA(ZFogBias, 0);
COPY_P3_DATA(FogMode, pSoftP3RX->P3RXFogMode);
COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
P3_DMA_COMMIT_BUFFER();
} // if (pContext->dwDirtyFlags & CONTEXT_DIRTY_FOG)
//*********************************************************
// Has any other texture state changed?
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_TEXTURE)
{
DISPDBG((DBGLVL," Texture State"));
_D3DChangeTextureP3RX(pContext);
DIRTY_GAMMA_STATE;
}
//*********************************************************
// Has the alphablend type changed?
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_ALPHABLEND)
{
// This _must_ be done after where _D3DChangeTextureP3RX is done,
// because it might need to change behaviour depending on
// the D3D pipeline.
P3_DMA_GET_BUFFER_ENTRIES(6);
if (pContext->RenderStates[D3DRENDERSTATE_BLENDENABLE] == FALSE)
{
if ( pContext->bAlphaBlendMustDoubleSourceColour )
{
// We need to double the source colour, even with no other blend.
pSoftP3RX->P3RXAlphaBlendAlphaMode.Enable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXAlphaBlendColorMode.Enable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXFBDestReadMode.ReadEnable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_ONE;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_ZERO;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceTimesTwo = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXAlphaBlendColorMode.DestTimesTwo = __PERMEDIA_DISABLE;
}
else
{
pSoftP3RX->P3RXAlphaBlendAlphaMode.Enable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXAlphaBlendColorMode.Enable = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXFBDestReadMode.ReadEnable = __PERMEDIA_DISABLE;
}
}
else
{
BOOL bSrcUsesDst, bSrcUsesSrc, bDstUsesSrc, bDstUsesDst;
pSoftP3RX->P3RXAlphaBlendAlphaMode.Enable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXAlphaBlendColorMode.Enable = __PERMEDIA_ENABLE;
if ( pContext->bAlphaBlendMustDoubleSourceColour )
{
pSoftP3RX->P3RXAlphaBlendColorMode.SourceTimesTwo = __PERMEDIA_ENABLE;
}
else
{
pSoftP3RX->P3RXAlphaBlendColorMode.SourceTimesTwo = __PERMEDIA_DISABLE;
}
pSoftP3RX->P3RXAlphaBlendColorMode.DestTimesTwo = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceTimesTwo = __PERMEDIA_DISABLE;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestTimesTwo = __PERMEDIA_DISABLE;
// Assumptions. Will be overridden below in certain cases.
// AusesB means that the A blend function uses the B data.
bSrcUsesSrc = TRUE;
bDstUsesSrc = FALSE;
bSrcUsesDst = FALSE;
bDstUsesDst = TRUE;
switch (pContext->RenderStates[D3DRENDERSTATE_SRCBLEND])
{
case D3DBLEND_BOTHSRCALPHA:
bDstUsesSrc = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
break;
case D3DBLEND_BOTHINVSRCALPHA:
bDstUsesSrc = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
break;
default:
// Not a short-hand blend mode, look at source and dest
switch (pContext->RenderStates[D3DRENDERSTATE_SRCBLEND])
{
case D3DBLEND_ZERO:
bSrcUsesSrc = FALSE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_ZERO;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_ZERO;
break;
case D3DBLEND_SRCCOLOR:
DISPDBG((ERRLVL,"Invalid Source Blend on P3RX D3DBLEND_SRCCOLOR"));
case D3DBLEND_INVSRCCOLOR:
DISPDBG((ERRLVL,"Invalid Source Blend on P3RX D3DBLEND_INVSRCCOLOR"));
//azn SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_ALPHA_BLEND );
// fall through
case D3DBLEND_ONE:
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_ONE;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_ONE;
break;
case D3DBLEND_SRCALPHA:
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
break;
case D3DBLEND_INVSRCALPHA:
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
break;
case D3DBLEND_DESTALPHA:
bSrcUsesDst = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_DST_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_DST_ALPHA;
break;
case D3DBLEND_INVDESTALPHA:
bSrcUsesDst = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_DST_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_DST_ALPHA;
break;
case D3DBLEND_DESTCOLOR:
bSrcUsesDst = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_DST_COLOR;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_DST_COLOR;
break;
case D3DBLEND_INVDESTCOLOR:
bSrcUsesDst = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_DST_COLOR;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_ONE_MINUS_DST_COLOR;
break;
case D3DBLEND_SRCALPHASAT:
bSrcUsesDst = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.SourceBlend = __GLINT_BLEND_FUNC_SRC_ALPHA_SATURATE;
pSoftP3RX->P3RXAlphaBlendAlphaMode.SourceBlend = __GLINT_BLEND_FUNC_SRC_ALPHA_SATURATE;
break;
default:
DISPDBG((ERRLVL,"Unknown Source Blend on P3RX"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_BLEND );
break;
}
switch(pContext->RenderStates[D3DRENDERSTATE_DESTBLEND])
{
case D3DBLEND_ZERO:
bDstUsesDst = FALSE;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_ZERO;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_ZERO;
break;
case D3DBLEND_DESTCOLOR:
DISPDBG((ERRLVL,"Invalid Source Blend on P3RX %d D3DBLEND_DESTCOLOR"));
case D3DBLEND_INVDESTCOLOR:
DISPDBG((ERRLVL,"Invalid Source Blend on P3RX %d D3DBLEND_INVDESTCOLOR"));
//azn SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_ALPHA_BLEND );
// fall through
case D3DBLEND_ONE:
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_ONE;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_ONE;
break;
case D3DBLEND_SRCCOLOR:
bDstUsesSrc = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_SRC_COLOR;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_SRC_COLOR;
if ( pContext->bAlphaBlendMustDoubleSourceColour )
{
// SRCCOLOR needs to be doubled.
pSoftP3RX->P3RXAlphaBlendColorMode.DestTimesTwo = __PERMEDIA_ENABLE;
}
break;
case D3DBLEND_INVSRCCOLOR:
bDstUsesSrc = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_COLOR;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_COLOR;
if ( pContext->bAlphaBlendMustDoubleSourceColour )
{
// Can't do this. What they want is:
// (1-(srccolor * 2))*destcolor
// = destcolor - 2*srccolor*destcolor
// All we can do is:
// (1-srccolor)*destcolor*2
// = destcolor*2 - 2*srccolor*destcolor
// ...which is a very different thing of course.
// Fail the blend.
SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_OP_HERE );
}
break;
case D3DBLEND_SRCALPHA:
bDstUsesSrc = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_SRC_ALPHA;
break;
case D3DBLEND_INVSRCALPHA:
bDstUsesSrc = TRUE;
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
break;
case D3DBLEND_DESTALPHA:
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_DST_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_DST_ALPHA;
break;
case D3DBLEND_INVDESTALPHA:
pSoftP3RX->P3RXAlphaBlendColorMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_DST_ALPHA;
pSoftP3RX->P3RXAlphaBlendAlphaMode.DestBlend = __GLINT_BLEND_FUNC_ONE_MINUS_DST_ALPHA;
break;
default:
DISPDBG((ERRLVL,"Unknown Destination Blend on P3RX"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
break;
}
if ( bSrcUsesDst || bDstUsesDst )
{
// Yep, using the destination data.
pSoftP3RX->P3RXFBDestReadMode.ReadEnable = __PERMEDIA_ENABLE;
}
else
{
pSoftP3RX->P3RXFBDestReadMode.ReadEnable = __PERMEDIA_DISABLE;
}
// We need to verify if the blending mode will use the alpha
// channel of the destination fragment (buffer) and if the buffer
// does in fact have an alpha buffer. If not, we need to make sure
// hw will assume this value == 1.0 (0xFF in ARGB).
// The D3DBLEND_SRCALPHASAT blend mode also involves the
// destination alpha
pSoftP3RX->P3RXAlphaBlendAlphaMode.NoAlphaBuffer = __PERMEDIA_DISABLE;
if ((pContext->RenderStates[D3DRENDERSTATE_DESTBLEND] == D3DBLEND_INVDESTALPHA) ||
(pContext->RenderStates[D3DRENDERSTATE_DESTBLEND] == D3DBLEND_DESTALPHA) ||
(pContext->RenderStates[D3DRENDERSTATE_SRCBLEND] == D3DBLEND_INVDESTALPHA) ||
(pContext->RenderStates[D3DRENDERSTATE_SRCBLEND] == D3DBLEND_DESTALPHA) ||
(pContext->RenderStates[D3DRENDERSTATE_SRCBLEND] == D3DBLEND_SRCALPHASAT))
{
if (!pContext->pSurfRenderInt->pFormatSurface->bAlpha)
{
pSoftP3RX->P3RXAlphaBlendAlphaMode.NoAlphaBuffer = __PERMEDIA_ENABLE;
}
}
// We could now check if the src data is ever used. If not, bin
// the whole previous pipeline! But this rarely happens.
// A case where it might is if they are updating just the Z buffer,
// but not changing the picture (e.g. for mirrors or portals).
}
COPY_P3_DATA(AlphaBlendAlphaMode, pSoftP3RX->P3RXAlphaBlendAlphaMode);
COPY_P3_DATA(AlphaBlendColorMode, pSoftP3RX->P3RXAlphaBlendColorMode);
COPY_P3_DATA(FBDestReadMode, pSoftP3RX->P3RXFBDestReadMode);
P3_DMA_COMMIT_BUFFER();
}
//*********************************************************
// Have w buffering parameters changed?
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_WBUFFER)
{
float noverf;
float NF_factor;
if ( (pContext->RenderStates[D3DRENDERSTATE_ZENABLE] == D3DZB_USEW) &&
(pContext->pSurfZBufferInt) )
{
DISPDBG((DBGLVL,"WBuffer wNear: %f, wFar: %f",
pContext->WBufferInfo.dvWNear,
pContext->WBufferInfo.dvWFar));
noverf = (pContext->WBufferInfo.dvWNear /
pContext->WBufferInfo.dvWFar);
NF_factor = (1.0 / 256.0);
// Compare range in decending order.
// Note that Exponent Width is determined
// as DepthMode.ExponentWidth +1
if (noverf >= (myPow(2,-0) * NF_factor))
{
// Use linear Z
pSoftP3RX->P3RXDepthMode.NonLinearZ = FALSE;
}
else if (noverf >= (myPow(2,-1) * NF_factor))
{
// Use exp width 1, exp scale 2
pSoftP3RX->P3RXDepthMode.ExponentWidth = 0;
pSoftP3RX->P3RXDepthMode.ExponentScale = 2;
pSoftP3RX->P3RXDepthMode.NonLinearZ = TRUE;
}
else if (noverf >= (myPow(2,-3) * NF_factor))
{
// Use exp width 2, exp scale 1
pSoftP3RX->P3RXDepthMode.ExponentWidth = 1;
pSoftP3RX->P3RXDepthMode.ExponentScale = 1;
pSoftP3RX->P3RXDepthMode.NonLinearZ = TRUE;
}
else if (noverf >= (myPow(2,-4) * NF_factor))
{
// Use exp width 2, exp scale 2
pSoftP3RX->P3RXDepthMode.ExponentWidth = 1;
pSoftP3RX->P3RXDepthMode.ExponentScale = 2;
pSoftP3RX->P3RXDepthMode.NonLinearZ = TRUE;
}
else if (noverf >= (myPow(2,-7) * NF_factor))
{
// Use exp width 3, exp scale 1
pSoftP3RX->P3RXDepthMode.ExponentWidth = 2;
pSoftP3RX->P3RXDepthMode.ExponentScale = 1;
pSoftP3RX->P3RXDepthMode.NonLinearZ = TRUE;
}
else
{
// Use exp width 3, exp scale 2
pSoftP3RX->P3RXDepthMode.ExponentWidth = 3;
pSoftP3RX->P3RXDepthMode.ExponentScale = 2;
pSoftP3RX->P3RXDepthMode.NonLinearZ = TRUE;
}
}
else
{
pSoftP3RX->P3RXDepthMode.NonLinearZ = FALSE;
}
P3_DMA_GET_BUFFER_ENTRIES(2);
COPY_P3_DATA(DepthMode, pSoftP3RX->P3RXDepthMode);
P3_DMA_COMMIT_BUFFER();
}
//*********************************************************
// Have the rendertarget/ z buffer address changed?
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_RENDER_OFFSETS)
{
DISPDBG((DBGLVL," Render Offsets"));
_D3D_OP_SetRenderTarget(pContext,
pContext->pSurfRenderInt,
pContext->pSurfZBufferInt,
FALSE);
P3_DMA_GET_BUFFER_ENTRIES(2);
COPY_P3_DATA(DeltaControl, pSoftP3RX->P3RX_P3DeltaControl);
P3_DMA_COMMIT_BUFFER();
}
//*********************************************************
// Have the viewport parameters changed?
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_VIEWPORT)
{
P3_DMA_GET_BUFFER_ENTRIES(12);
DISPDBG((DBGLVL,"Viewport left: %d, top: %d, width: %d, height: %d",
pContext->ViewportInfo.dwX,
pContext->ViewportInfo.dwY,
pContext->ViewportInfo.dwWidth,
pContext->ViewportInfo.dwHeight));
// If a valid viewport is setup, scissor it
if ((pContext->ViewportInfo.dwWidth != 0) &&
(pContext->ViewportInfo.dwHeight != 0))
{
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
if (pContext->Flags & SURFACE_ANTIALIAS)
{
pSoftP3RX->P3RXScissorMinXY.X = pContext->ViewportInfo.dwX * 2;
pSoftP3RX->P3RXScissorMinXY.Y = pContext->ViewportInfo.dwY * 2;
pSoftP3RX->P3RXScissorMaxXY.X = (pContext->ViewportInfo.dwWidth * 2) +
pContext->ViewportInfo.dwX;
pSoftP3RX->P3RXScissorMaxXY.Y = (pContext->ViewportInfo.dwHeight * 2) +
pContext->ViewportInfo.dwY;
}
else
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
{
pSoftP3RX->P3RXScissorMinXY.X = pContext->ViewportInfo.dwX;
pSoftP3RX->P3RXScissorMinXY.Y = pContext->ViewportInfo.dwY;
pSoftP3RX->P3RXScissorMaxXY.X = pContext->ViewportInfo.dwWidth +
pContext->ViewportInfo.dwX;
pSoftP3RX->P3RXScissorMaxXY.Y = pContext->ViewportInfo.dwHeight +
pContext->ViewportInfo.dwY;
}
COPY_P3_DATA(ScissorMinXY, pSoftP3RX->P3RXScissorMinXY);
COPY_P3_DATA(ScissorMaxXY, pSoftP3RX->P3RXScissorMaxXY);
SEND_P3_DATA(YLimits, (pContext->ViewportInfo.dwY & 0xFFFF) |
(pSoftP3RX->P3RXScissorMaxXY.Y << 16));
SEND_P3_DATA(XLimits, (pContext->ViewportInfo.dwX & 0xFFFF) |
(pSoftP3RX->P3RXScissorMaxXY.X << 16));
// Enable user scissor
SEND_P3_DATA(ScissorMode, 1);
pSoftP3RX->P3RXRasterizerMode.YLimitsEnable = __PERMEDIA_ENABLE;
COPY_P3_DATA(RasterizerMode, pSoftP3RX->P3RXRasterizerMode);
}
else
{
SEND_P3_DATA(ScissorMode, 0);
pSoftP3RX->P3RXRasterizerMode.YLimitsEnable = __PERMEDIA_DISABLE;
COPY_P3_DATA(RasterizerMode, pSoftP3RX->P3RXRasterizerMode);
}
P3_DMA_COMMIT_BUFFER();
}
//*********************************************************
// Can we optimize the pipeline? (Depends on misc. RS)
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_PIPELINEORDER)
{
// Must switch over the router mode if we are testing and expect
// the Z to be discarded.
P3_DMA_GET_BUFFER_ENTRIES(2);
DISPDBG((DBGLVL, " Pipeline order"));
if (((pContext->RenderStates[D3DRENDERSTATE_ALPHATESTENABLE]) ||
(pContext->RenderStates[D3DRENDERSTATE_COLORKEYENABLE])) &&
(pContext->RenderStates[D3DRENDERSTATE_ZWRITEENABLE]))
{
SEND_P3_DATA(RouterMode, __PERMEDIA_DISABLE);
}
else
{
SEND_P3_DATA(RouterMode, __PERMEDIA_ENABLE);
}
P3_DMA_COMMIT_BUFFER();
}
//*********************************************************
// Can we optimize the alpha pipeline? (Depends on misc. RS)
//*********************************************************
// DO AT THE END
//*********************************************************
if (pContext->dwDirtyFlags & CONTEXT_DIRTY_OPTIMIZE_ALPHA)
{
P3_DMA_GET_BUFFER_ENTRIES(6);
DISPDBG((DBGLVL, " Alpha optimizations"));
pSoftP3RX->P3RXFBDestReadMode.AlphaFiltering = __PERMEDIA_DISABLE;
// There may be an optimization when blending is on
if (pContext->RenderStates[D3DRENDERSTATE_BLENDENABLE])
{
// Check the RouterMode path
if (((pContext->RenderStates[D3DRENDERSTATE_ALPHATESTENABLE]) ||
(pContext->RenderStates[D3DRENDERSTATE_COLORKEYENABLE])) &&
(pContext->RenderStates[D3DRENDERSTATE_ZWRITEENABLE]))
{
// Slow mode
}
else
{
// Fast mode. The Z value will be written before the alpha test. This means that we
// can use the alpha test to discard pixels if it is not already in use.
if (!(pContext->RenderStates[D3DRENDERSTATE_ALPHATESTENABLE]) &&
!(pContext->RenderStates[D3DRENDERSTATE_COLORKEYENABLE]))
{
// Check for known blends.
if ((pContext->RenderStates[D3DRENDERSTATE_SRCBLEND] == D3DBLEND_BOTHSRCALPHA) ||
((pContext->RenderStates[D3DRENDERSTATE_SRCBLEND] == D3DBLEND_SRCALPHA) &&
(pContext->RenderStates[D3DRENDERSTATE_DESTBLEND] == D3DBLEND_INVSRCALPHA)))
{
// SRCALPHA:INVSRCALPH
pSoftP3RX->P3RXAlphaTestMode.Reference = 0;
pSoftP3RX->P3RXAlphaTestMode.Enable = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXAlphaTestMode.Compare = __GLINT_ALPHA_COMPARE_MODE_GREATER;
pSoftP3RX->P3RXFBDestReadMode.AlphaFiltering = __PERMEDIA_ENABLE;
pSoftP3RX->P3RXFBDestReadEnables.ReferenceAlpha = 0xFF;
}
}
}
}
COPY_P3_DATA(FBDestReadEnables, pSoftP3RX->P3RXFBDestReadEnables);
COPY_P3_DATA(FBDestReadMode, pSoftP3RX->P3RXFBDestReadMode);
COPY_P3_DATA(AlphaTestMode, pSoftP3RX->P3RXAlphaTestMode);
P3_DMA_COMMIT_BUFFER();
}
} // __ST_HandleDirtyP3State
//-----------------------------------------------------------------------------
//
// _D3D_ST_ProcessOneRenderState
//
//-----------------------------------------------------------------------------
#define NOT_HANDLED DISPDBG((DBGLVL, " **Not Currently Handled**"));
DWORD
_D3D_ST_ProcessOneRenderState(
P3_D3DCONTEXT* pContext,
DWORD dwRSType,
DWORD dwRSVal)
{
P3_SOFTWARECOPY* pSoftP3RX;
P3_THUNKEDDATA *pThisDisplay = pContext->pThisDisplay;
DWORD *pFlags;
DWORD *pdwTextureStageState_0, *pdwTextureStageState_1;
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
BOOL bDX7_Antialiasing = FALSE;
#endif // DX8_MULTISAMPLING || DX7_ANTIALIASING
P3_DMA_DEFS();
DBG_ENTRY(_D3D_ST_ProcessOneRenderState);
pSoftP3RX = &pContext->SoftCopyGlint;
DISPDBG((DBGLVL, "_D3D_ST_ProcessOneRenderState: dwType =%08lx, dwVal=%d",
dwRSType, dwRSVal));
if (dwRSType >= D3DHAL_MAX_RSTATES)
{
DISPDBG((WRNLVL, "_D3D_ST_ProcessOneRenderState: OUT OF RANGE"
" dwType =%08lx, dwVal=%d", dwRSType, dwRSVal));
return DD_OK;
}
// Store the state in the context
pContext->RenderStates[dwRSType] = dwRSVal;
// Prepare pointer to the contexts state flags for updates
pFlags = &pContext->Flags;
// Prepare pointers to the stored TSS in case we need them
pdwTextureStageState_0 =
&(pContext->TextureStageState[TEXSTAGE_0].m_dwVal[0]);
pdwTextureStageState_1 =
&(pContext->TextureStageState[TEXSTAGE_1].m_dwVal[0]);
// Prepare DMA Buffer for 8 entries in case we need to add to it
P3_DMA_GET_BUFFER();
P3_ENSURE_DX_SPACE(8);
WAIT_FIFO(8);
// Process according to the type of renderstate. For multivalued
// renderstates do some kind of value checking and make sure to
// setup valid defaults where needed.
switch (dwRSType)
{
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// The following are D3D renderstates which are still in use by DX8 Apps
//----------------------------------------------------------------------
//----------------------------------------------------------------------
case D3DRENDERSTATE_ZENABLE:
DISPDBG((DBGLVL, "SET D3DRS_ZENABLE = 0x%x",dwRSVal));
DIRTY_ZBUFFER(pContext);
break;
case D3DRENDERSTATE_FILLMODE:
DISPDBG((DBGLVL, "SET D3DRS_FILLMODE = 0x%x",dwRSVal));
switch (dwRSVal)
{
case D3DFILL_POINT:
case D3DFILL_WIREFRAME:
case D3DFILL_SOLID:
// These values are OK
break;
default:
// We've received an illegal value, default to solid fills...
DISPDBG((ERRLVL,"_D3D_ST_ProcessOneRenderState: "
"unknown FILLMODE value"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
pContext->RenderStates[D3DRENDERSTATE_FILLMODE] =
D3DFILL_SOLID;
break;
}
break;
case D3DRENDERSTATE_SHADEMODE:
DISPDBG((DBGLVL, "SET D3DRS_SHADEMODE = 0x%x",dwRSVal));
switch(dwRSVal)
{
case D3DSHADE_PHONG:
// Can't actually do Phong, but everyone knows this and
// assumes we use Gouraud instead.
SET_BLEND_ERROR ( pContext, BS_PHONG_SHADING );
// fall through and setup Gouraud instead
case D3DSHADE_GOURAUD:
pSoftP3RX->ColorDDAMode.UnitEnable = 1;
pSoftP3RX->ColorDDAMode.ShadeMode = 1;
COPY_P3_DATA(ColorDDAMode, pSoftP3RX->ColorDDAMode);
pSoftP3RX->P3RX_P3DeltaMode.SmoothShadingEnable = 1;
pSoftP3RX->P3RX_P3DeltaControl.UseProvokingVertex = 0;
pSoftP3RX->P3RX_P3VertexControl.Flat = 0;
COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
COPY_P3_DATA(DeltaControl, pSoftP3RX->P3RX_P3DeltaControl);
COPY_P3_DATA(VertexControl, pSoftP3RX->P3RX_P3VertexControl);
*pFlags |= SURFACE_GOURAUD;
// If we are texturing, some changes may need to be made
if (pdwTextureStageState_0[D3DTSS_TEXTUREMAP] != 0)
{
DIRTY_TEXTURE(pContext);
}
break;
case D3DSHADE_FLAT:
pSoftP3RX->ColorDDAMode.UnitEnable = 1;
pSoftP3RX->ColorDDAMode.ShadeMode = 0;
COPY_P3_DATA(ColorDDAMode, pSoftP3RX->ColorDDAMode);
pSoftP3RX->P3RX_P3DeltaMode.SmoothShadingEnable = 0;
pSoftP3RX->P3RX_P3DeltaControl.UseProvokingVertex = 1;
pSoftP3RX->P3RX_P3VertexControl.Flat = 1;
COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
COPY_P3_DATA(DeltaControl, pSoftP3RX->P3RX_P3DeltaControl);
COPY_P3_DATA(VertexControl, pSoftP3RX->P3RX_P3VertexControl);
*pFlags &= ~SURFACE_GOURAUD;
// If we are texturing, some changes may need to be made
if (pdwTextureStageState_0[D3DTSS_TEXTUREMAP] != 0)
{
DIRTY_TEXTURE(pContext);
}
break;
default:
DISPDBG((ERRLVL,"_D3D_ST_ProcessOneRenderState: "
"unknown SHADEMODE value"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
break;
case D3DRENDERSTATE_LINEPATTERN:
DISPDBG((DBGLVL, "SET D3DRS_LINEPATTERN = 0x%x",dwRSVal));
if (dwRSVal == 0)
{
pSoftP3RX->PXRXLineStippleMode.StippleEnable = __PERMEDIA_DISABLE;
RENDER_LINE_STIPPLE_DISABLE(pContext->RenderCommand);
}
else
{
pSoftP3RX->PXRXLineStippleMode.StippleEnable = __PERMEDIA_ENABLE;
pSoftP3RX->PXRXLineStippleMode.RepeatFactor =
(dwRSVal & 0x0000FFFF) -1 ;
pSoftP3RX->PXRXLineStippleMode.StippleMask =
(dwRSVal & 0xFFFF0000) >> 16;
pSoftP3RX->PXRXLineStippleMode.Mirror = __PERMEDIA_DISABLE;
RENDER_LINE_STIPPLE_ENABLE(pContext->RenderCommand);
}
COPY_P3_DATA( LineStippleMode, pSoftP3RX->PXRXLineStippleMode);
break;
case D3DRENDERSTATE_ZWRITEENABLE:
DISPDBG((DBGLVL, "SET D3DRS_ZWRITEENABLE = 0x%x",dwRSVal));
if (dwRSVal != 0)
{
// Local Buffer Write mode
if(!(*pFlags & SURFACE_ZWRITEENABLE))
{
DISPDBG((DBGLVL, "Enabling Z Writes"));
*pFlags |= SURFACE_ZWRITEENABLE;
DIRTY_ZBUFFER(pContext);
DIRTY_PIPELINEORDER(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
}
}
else
{
if (*pFlags & SURFACE_ZWRITEENABLE)
{
DISPDBG((DBGLVL, "Disabling Z Writes"));
*pFlags &= ~SURFACE_ZWRITEENABLE;
DIRTY_ZBUFFER(pContext);
DIRTY_PIPELINEORDER(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
}
}
break;
case D3DRENDERSTATE_ALPHATESTENABLE:
DISPDBG((DBGLVL, "SET D3DRS_ALPHATESTENABLE = 0x%x",dwRSVal));
DIRTY_ALPHATEST(pContext);
DIRTY_PIPELINEORDER(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
break;
case D3DRENDERSTATE_LASTPIXEL:
DISPDBG((DBGLVL, "SET D3DRS_LASTPIXEL = 0x%x",dwRSVal));
NOT_HANDLED;
break;
case D3DRENDERSTATE_SRCBLEND:
DISPDBG((DBGLVL, "SET D3DRS_SRCBLEND = 0x%x",dwRSVal));
DIRTY_ALPHABLEND(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
break;
case D3DRENDERSTATE_DESTBLEND:
DISPDBG((DBGLVL, "SET D3DRS_DESTBLEND = 0x%x",dwRSVal));
DIRTY_ALPHABLEND(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
break;
case D3DRENDERSTATE_CULLMODE:
DISPDBG((DBGLVL, "SET D3DRS_CULLMODE = 0x%x",dwRSVal));
switch(dwRSVal)
{
case D3DCULL_NONE:
SET_CULLING_TO_NONE(pContext);
pSoftP3RX->P3RX_P3DeltaMode.BackfaceCull = 0;
break;
case D3DCULL_CCW:
SET_CULLING_TO_CCW(pContext);
pSoftP3RX->P3RX_P3DeltaMode.BackfaceCull = 0;
break;
case D3DCULL_CW:
SET_CULLING_TO_CW(pContext);
pSoftP3RX->P3RX_P3DeltaMode.BackfaceCull = 0;
break;
default:
DISPDBG((ERRLVL,"_D3D_ST_ProcessOneRenderState: "
"unknown cull mode"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
break;
case D3DRENDERSTATE_ZFUNC:
DISPDBG((DBGLVL, "SET D3DRS_ZFUNC = 0x%x",dwRSVal));
switch (dwRSVal)
{
case D3DCMP_NEVER:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_NEVER;
break;
case D3DCMP_LESS:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_LESS;
break;
case D3DCMP_EQUAL:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_EQUAL;
break;
case D3DCMP_LESSEQUAL:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_LESS_OR_EQUAL;
break;
case D3DCMP_GREATER:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_GREATER;
break;
case D3DCMP_NOTEQUAL:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_NOT_EQUAL;
break;
case D3DCMP_GREATEREQUAL:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_GREATER_OR_EQUAL;
break;
case D3DCMP_ALWAYS:
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_ALWAYS;
break;
default:
DISPDBG((ERRLVL,"_D3D_ST_ProcessOneRenderState: "
"unknown ZFUNC mode"));
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
// Set Less or equal as default
pSoftP3RX->P3RXDepthMode.CompareMode =
__GLINT_DEPTH_COMPARE_MODE_LESS_OR_EQUAL;
break;
}
DIRTY_ZBUFFER(pContext);
break;
case D3DRENDERSTATE_ALPHAREF:
DISPDBG((DBGLVL, "SET D3DRS_ALPHAREF = 0x%x",dwRSVal));
DIRTY_ALPHATEST(pContext);
break;
case D3DRENDERSTATE_ALPHAFUNC:
DISPDBG((DBGLVL, "SET D3DRS_ALPHAFUNC = 0x%x",dwRSVal));
DIRTY_ALPHATEST(pContext);
break;
case D3DRENDERSTATE_DITHERENABLE:
DISPDBG((DBGLVL, "SET D3DRS_DITHERENABLE = 0x%x",dwRSVal));
if (dwRSVal != 0)
{
pSoftP3RX->DitherMode.DitherEnable = __PERMEDIA_ENABLE;
}
else
{
pSoftP3RX->DitherMode.DitherEnable = __PERMEDIA_DISABLE;
}
COPY_P3_DATA(DitherMode, pSoftP3RX->DitherMode);
break;
case D3DRENDERSTATE_BLENDENABLE:
DISPDBG((DBGLVL, "SET D3DRS_BLENDENABLE = 0x%x",dwRSVal));
// Although render states whose values are boolean in type are
// documented as only accepting TRUE(1) and FALSE(0) the runtime
// does not validate this and accepts any non-zero value as true.
// The sample driver interprets this strictly and does interpret
// values other than 1 as being TRUE. However, as the runtime
// does not offer validation your driver should interpret 0 as
// FALSE and any other non-zero value as TRUE.
if (dwRSVal != 0)
{
if(!(*pFlags & SURFACE_ALPHAENABLE))
{
// Set the blend enable flag in the render context struct
*pFlags |= SURFACE_ALPHAENABLE;
DIRTY_ALPHABLEND(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
}
}
else
{
if (*pFlags & SURFACE_ALPHAENABLE)
{
// Turn off blend enable flag in render context struct
*pFlags &= ~SURFACE_ALPHAENABLE;
DIRTY_ALPHABLEND(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
}
}
break;
case D3DRENDERSTATE_FOGENABLE:
DISPDBG((DBGLVL, "SET D3DRS_FOGENABLE = 0x%x",dwRSVal));
DIRTY_FOG(pContext);
break;
case D3DRENDERSTATE_SPECULARENABLE:
DISPDBG((DBGLVL, "SET D3DRS_SPECULARENABLE = 0x%x",dwRSVal));
if (dwRSVal)
{
*pFlags |= SURFACE_SPECULAR;
pSoftP3RX->P3RXTextureApplicationMode.EnableKs = __PERMEDIA_ENABLE;
pSoftP3RX->P3RX_P3DeltaMode.SpecularTextureEnable = 1;
}
else
{
*pFlags &= ~SURFACE_SPECULAR;
pSoftP3RX->P3RXTextureApplicationMode.EnableKs = __PERMEDIA_DISABLE;
pSoftP3RX->P3RX_P3DeltaMode.SpecularTextureEnable = 0;
}
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_ZVISIBLE:
DISPDBG((DBGLVL, "SET D3DRS_ZVISIBLE = %d", dwRSVal));
if (dwRSVal)
{
DISPDBG((ERRLVL,"_D3D_ST_ProcessOneRenderState:"
" ZVISIBLE enabled - no longer supported."));
}
break;
case D3DRENDERSTATE_STIPPLEDALPHA:
DISPDBG((DBGLVL, "SET D3DRS_STIPPLEDALPHA = 0x%x",dwRSVal));
if(dwRSVal)
{
if (!(*pFlags & SURFACE_ALPHASTIPPLE))
{
*pFlags |= SURFACE_ALPHASTIPPLE;
if (pContext->bKeptStipple)
{
RENDER_AREA_STIPPLE_DISABLE(pContext->RenderCommand);
}
}
}
else
{
if (*pFlags & SURFACE_ALPHASTIPPLE)
{
// If Alpha Stipple is being turned off, turn the normal
// stipple back on, and enable it.
int i;
for (i = 0; i < 32; i++)
{
P3_ENSURE_DX_SPACE(2);
WAIT_FIFO(2);
SEND_P3_DATA_OFFSET(AreaStipplePattern0,
(DWORD)pContext->CurrentStipple[i], i);
}
*pFlags &= ~SURFACE_ALPHASTIPPLE;
if (pContext->bKeptStipple)
{
RENDER_AREA_STIPPLE_ENABLE(pContext->RenderCommand);
}
}
}
break;
case D3DRENDERSTATE_FOGCOLOR:
DISPDBG((DBGLVL, "SET D3DRS_FOGCOLOR = 0x%x",dwRSVal));
DIRTY_FOG(pContext);
break;
case D3DRENDERSTATE_FOGTABLEMODE:
DISPDBG((DBGLVL, "SET D3DRS_FOGTABLEMODE = 0x%x", dwRSVal));
DIRTY_FOG(pContext);
break;
case D3DRENDERSTATE_FOGTABLESTART:
DISPDBG((DBGLVL, "SET D3DRS_FOGTABLESTART = 0x%x",dwRSVal));
DIRTY_FOG(pContext);
break;
case D3DRENDERSTATE_FOGTABLEEND:
DISPDBG((DBGLVL, "SET D3DRS_FOGTABLEEND = 0x%x",dwRSVal));
DIRTY_FOG(pContext);
break;
case D3DRENDERSTATE_FOGTABLEDENSITY:
DISPDBG((DBGLVL, "SET D3DRS_FOGTABLEDENSITY = 0x%x",dwRSVal));
DIRTY_FOG(pContext);
break;
case D3DRENDERSTATE_EDGEANTIALIAS:
DISPDBG((DBGLVL, "SET D3DRS_EDGEANTIALIAS = 0x%x",dwRSVal));
NOT_HANDLED;
break;
case D3DRENDERSTATE_ZBIAS:
DISPDBG((DBGLVL, "SET D3DRS_ZBIAS = 0x%x",dwRSVal));
NOT_HANDLED;
break;
case D3DRENDERSTATE_RANGEFOGENABLE:
DISPDBG((DBGLVL, "SET D3DRS_RANGEFOGENABLE = 0x%x",dwRSVal));
NOT_HANDLED;
break;
case D3DRENDERSTATE_STENCILENABLE:
DISPDBG((DBGLVL, "SET D3DRS_STENCILENABLE = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_STENCILFAIL:
DISPDBG((DBGLVL, "SET D3DRS_STENCILFAIL = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_STENCILZFAIL:
DISPDBG((DBGLVL, "SET D3DRS_STENCILZFAIL = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_STENCILPASS:
DISPDBG((DBGLVL, "SET D3DRS_STENCILPASS = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_STENCILFUNC:
DISPDBG((DBGLVL, "SET D3DRS_STENCILFUNC = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_STENCILREF:
DISPDBG((DBGLVL, "SET D3DRS_STENCILREF = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_STENCILMASK:
DISPDBG((DBGLVL, "SET D3DRS_STENCILMASK = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_STENCILWRITEMASK:
DISPDBG((DBGLVL, "SET D3DRS_STENCILENABLE = 0x%x", dwRSVal));
DIRTY_STENCIL(pContext);
break;
case D3DRENDERSTATE_TEXTUREFACTOR:
// Should not need to dirty anything. This is a good thing -
// this may be changed frequently in between calls, and may be
// the only thing to change. Used for some of the odder blend modes.
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREFACTOR = 0x%x", dwRSVal));
SEND_P3_DATA ( TextureEnvColor, FORMAT_8888_32BIT_BGR(dwRSVal) );
SEND_P3_DATA ( TextureCompositeFactor0, FORMAT_8888_32BIT_BGR(dwRSVal) );
SEND_P3_DATA ( TextureCompositeFactor1, FORMAT_8888_32BIT_BGR(dwRSVal) );
break;
case D3DRENDERSTATE_WRAP0:
case D3DRENDERSTATE_WRAP1:
case D3DRENDERSTATE_WRAP2:
case D3DRENDERSTATE_WRAP3:
case D3DRENDERSTATE_WRAP4:
case D3DRENDERSTATE_WRAP5:
case D3DRENDERSTATE_WRAP6:
case D3DRENDERSTATE_WRAP7:
DISPDBG((DBGLVL, "SET D3DRS_WRAP %d = 0x%x",
dwRSType - D3DRENDERSTATE_WRAP0, (DWORD)dwRSVal));
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_LOCALVIEWER:
DISPDBG((DBGLVL, "SET D3DRS_LOCALVIEWER = %d", dwRSVal));
DIRTY_GAMMA_STATE;
break;
case D3DRENDERSTATE_CLIPPING:
DISPDBG((DBGLVL, "SET D3DRS_CLIPPING = %d", dwRSVal));
DIRTY_GAMMA_STATE;
break;
case D3DRENDERSTATE_LIGHTING:
DISPDBG((DBGLVL, "SET D3DRS_LIGHTING = %d", dwRSVal));
DIRTY_GAMMA_STATE;
break;
case D3DRENDERSTATE_AMBIENT:
DISPDBG((DBGLVL, "SET D3DRS_AMBIENT = 0x%x", dwRSVal));
DIRTY_GAMMA_STATE;
break;
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// The following are internal D3D renderstates which are created by
// the runtime. Apps don't send them.
//----------------------------------------------------------------------
//----------------------------------------------------------------------
case D3DRENDERSTATE_SCENECAPTURE:
DISPDBG((DBGLVL, "SET D3DRS_SCENECAPTURE = 0x%x", dwRSVal));
{
DWORD dwFlag;
if (dwRSVal)
{
dwFlag = D3DHAL_SCENE_CAPTURE_START;
}
else
{
dwFlag = D3DHAL_SCENE_CAPTURE_END;
}
#if DX7_TEXMANAGEMENT
if (dwRSVal)
{
// Reset Texture Management counters for next frame
_D3D_TM_STAT_ResetCounters(pContext);
}
#endif // DX7_TEXMANAGEMENT
// Flush all DMA ops before going to next frame
P3_DMA_COMMIT_BUFFER();
_D3D_OP_SceneCapture(pContext, dwFlag);
// Restart DMA ops
P3_DMA_GET_BUFFER();
}
break;
#if DX7_TEXMANAGEMENT
case D3DRENDERSTATE_EVICTMANAGEDTEXTURES:
DISPDBG((DBGLVL, "SET D3DRENDERSTATE_EVICTMANAGEDTEXTURES = 0x%x",
dwRSVal));
if (NULL != pContext->pTextureManager)
{
_D3D_TM_EvictAllManagedTextures(pContext);
}
break;
#endif // DX7_TEXMANAGEMENT
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// The following are new DX8 renderstates which we need to process
// correctly in order to run DX8 apps
//----------------------------------------------------------------------
//----------------------------------------------------------------------
#if DX8_POINTSPRITES
// Pointsprite support
case D3DRS_POINTSIZE:
DISPDBG((DBGLVL, "SET D3DRS_POINTSIZE = 0x%x",dwRSVal));
*(DWORD*)(&pContext->PntSprite.fSize) = dwRSVal;
break;
case D3DRS_POINTSPRITEENABLE:
DISPDBG((DBGLVL, "SET D3DRS_POINTSPRITEENABLE = 0x%x",dwRSVal));
pContext->PntSprite.bEnabled = dwRSVal;
break;
case D3DRS_POINTSIZE_MIN:
DISPDBG((DBGLVL, "SET D3DRS_POINTSIZE_MIN = 0x%x",dwRSVal));
*(DWORD*)(&pContext->PntSprite.fSizeMin) = dwRSVal;
break;
case D3DRS_POINTSIZE_MAX:
DISPDBG((DBGLVL, "SET D3DRS_POINTSIZE_MAX = 0x%x",dwRSVal));
*(DWORD*)(&pContext->PntSprite.fSizeMax) = dwRSVal;
break;
// All of the following point sprite related render states are
// ignored by this driver since we are a Non-TnLHal driver.
case D3DRS_POINTSCALEENABLE:
DISPDBG((DBGLVL, "SET D3DRS_POINTSCALEENABLE = 0x%x",dwRSVal));
pContext->PntSprite.bScaleEnabled = dwRSVal;
break;
case D3DRS_POINTSCALE_A:
DISPDBG((DBGLVL, "SET D3DRS_POINTSCALE_A = 0x%x",dwRSVal));
*(DWORD*)(&pContext->PntSprite.fScale_A) = dwRSVal;
break;
case D3DRS_POINTSCALE_B:
DISPDBG((DBGLVL, "SET D3DRS_POINTSCALE_B = 0x%x",dwRSVal));
*(DWORD*)(&pContext->PntSprite.fScale_B) = dwRSVal;
break;
case D3DRS_POINTSCALE_C:
DISPDBG((DBGLVL, "SET D3DRS_POINTSCALE_C = 0x%x",dwRSVal));
*(DWORD*)(&pContext->PntSprite.fScale_C) = dwRSVal;
break;
#endif // DX8_POINTSPRITES
#if DX8_VERTEXSHADERS
case D3DRS_SOFTWAREVERTEXPROCESSING:
DISPDBG((DBGLVL, "SET D3DRS_SOFTWAREVERTEXPROCESSING = 0x%x",dwRSVal));
NOT_HANDLED;
break;
#endif // DX8_VERTEXSHADERS
#if DX8_DDI
case D3DRS_COLORWRITEENABLE:
{
DWORD dwColMask = 0x0;
DISPDBG((DBGLVL, "SET D3DRS_COLORWRITEENABLE = 0x%x",dwRSVal));
if (dwRSVal & D3DCOLORWRITEENABLE_RED)
{
dwColMask |= pContext->pSurfRenderInt->pixFmt.dwRBitMask;
}
if (dwRSVal & D3DCOLORWRITEENABLE_GREEN)
{
dwColMask |= pContext->pSurfRenderInt->pixFmt.dwGBitMask;
}
if (dwRSVal & D3DCOLORWRITEENABLE_BLUE)
{
dwColMask |= pContext->pSurfRenderInt->pixFmt.dwBBitMask;
}
if (dwRSVal & D3DCOLORWRITEENABLE_ALPHA)
{
dwColMask |= pContext->pSurfRenderInt->pixFmt.dwRGBAlphaBitMask;
}
// Replicate mask into higher word for P3 in 16 bpp mode
if (pContext->pSurfRenderInt->dwPixelSize == __GLINT_16BITPIXEL)
{
dwColMask |= (dwColMask << 16);
pContext->dwColorWriteSWMask = dwColMask;
}
else
{
pContext->dwColorWriteSWMask = 0xFFFFFFFF;
}
pContext->dwColorWriteHWMask = dwColMask;
SEND_P3_DATA(FBHardwareWriteMask, pContext->dwColorWriteHWMask);
DISPDBG((DBGLVL,"dwColMask = 0x%08x",dwColMask));
SEND_P3_DATA(FBSoftwareWriteMask, pContext->dwColorWriteSWMask);
}
break;
#endif // DX8_DDI
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// The following are retired renderstates from DX8 but which we need to
// process correctly in order to run apps which use legacy interfaces
// These apps might send down the pipeline these renderstates and expect
// correct driver behavior !
//----------------------------------------------------------------------
//----------------------------------------------------------------------
case D3DRENDERSTATE_TEXTUREHANDLE:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREHANDLE = 0x%x",dwRSVal));
if (dwRSVal != pdwTextureStageState_0[D3DTSS_TEXTUREMAP])
{
pdwTextureStageState_0[D3DTSS_TEXTUREMAP] = dwRSVal;
DIRTY_TEXTURE(pContext);
}
break;
#if DX7_ANTIALIAS
// DX7 uses D3DRENDERSTATE_ANTIALIAS.
case D3DRENDERSTATE_ANTIALIAS:
bDX7_Antialiasing = TRUE;
if (dwRSVal && pContext->pSurfRenderInt)
{
// Always reallocate alias buffer for DX7
// P3 driver supports only 2x2 (4) multi sample antialiasing
#if DX8_MULTISAMPLING
pContext->pSurfRenderInt->dwSampling = 4;
#endif // DX8_MULTISAMPLING
if (! _D3D_ST_CanRenderAntialiased(pContext, TRUE))
{
#if DX8_MULTISAMPLING
// Reset dwSampling in case of failure
pContext->pSurfRenderInt->dwSampling = 0;
#endif // DX8_MULTISAMPLING
P3_DMA_COMMIT_BUFFER();
return DDERR_OUTOFMEMORY;
}
}
// then fall through...
#endif // DX7_ANTIALIAS
#if DX8_MULTISAMPLING
// DX8 uses D3DRS_MULTISAMPLEANTIALIAS
case D3DRS_MULTISAMPLEANTIALIAS:
#endif // DX8_MULTISAMPLING
#if DX8_MULTISAMPLING || DX7_ANTIALIAS
DISPDBG((DBGLVL, "ChangeState: AntiAlias 0x%x",dwRSVal));
P3_DMA_COMMIT_BUFFER();
if (dwRSVal
#if DX8_MULTISAMPLING
&& pContext->pSurfRenderInt->dwSampling
#endif // DX8_MULTISAMPLING
)
{
pSoftP3RX->P3RX_P3DeltaControl.FullScreenAA = __PERMEDIA_ENABLE;
*pFlags |= SURFACE_ANTIALIAS;
}
else
{
pSoftP3RX->P3RX_P3DeltaControl.FullScreenAA = __PERMEDIA_DISABLE;
*pFlags &= ~SURFACE_ANTIALIAS;
}
P3_DMA_GET_BUFFER_ENTRIES( 4 );
DIRTY_RENDER_OFFSETS(pContext);
break;
#endif // DX8_MULTISAMPLING || DX7_ANTIALIAS
case D3DRENDERSTATE_TEXTUREPERSPECTIVE:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREPERSPECTIVE = 0x%x",dwRSVal));
if (dwRSVal != 0)
{
*pFlags |= SURFACE_PERSPCORRECT;
pSoftP3RX->P3RX_P3DeltaControl.ForceQ = 0;
}
else
{
*pFlags &= ~SURFACE_PERSPCORRECT;
pSoftP3RX->P3RX_P3DeltaControl.ForceQ = 1;
}
COPY_P3_DATA(DeltaControl, pSoftP3RX->P3RX_P3DeltaControl);
break;
case D3DRENDERSTATE_TEXTUREMAPBLEND:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREMAPBLEND = 0x%x", dwRSVal));
*pFlags &= ~SURFACE_MODULATE;
switch(dwRSVal)
{
case D3DTBLEND_DECALMASK: // unsupported - do decal as fallback.
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_COLOR_OP );
// fall through
case D3DTBLEND_DECAL:
case D3DTBLEND_COPY:
pdwTextureStageState_0[D3DTSS_COLOROP] = D3DTOP_SELECTARG1;
pdwTextureStageState_0[D3DTSS_COLORARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
pdwTextureStageState_0[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
pdwTextureStageState_1[D3DTSS_COLOROP] = D3DTOP_DISABLE;
break;
case D3DTBLEND_MODULATEMASK: // unsupported - do modulate as fallback.
SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_COLOR_OP );
// fall through
case D3DTBLEND_MODULATE:
pdwTextureStageState_0[D3DTSS_COLOROP] = D3DTOP_MODULATE;
pdwTextureStageState_0[D3DTSS_COLORARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
// In the changetexture* code we modify the below value,
// dependent on the SURFACE_MODULATE flag...
pdwTextureStageState_0[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
pdwTextureStageState_0[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
pdwTextureStageState_1[D3DTSS_COLOROP] = D3DTOP_DISABLE;
*pFlags |= SURFACE_MODULATE;
break;
case D3DTBLEND_MODULATEALPHA:
pdwTextureStageState_0[D3DTSS_COLOROP] = D3DTOP_MODULATE;
pdwTextureStageState_0[D3DTSS_COLORARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
pdwTextureStageState_0[D3DTSS_ALPHAOP] = D3DTOP_MODULATE;
pdwTextureStageState_0[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
pdwTextureStageState_1[D3DTSS_COLOROP] = D3DTOP_DISABLE;
break;
case D3DTBLEND_DECALALPHA:
pdwTextureStageState_0[D3DTSS_COLOROP] = D3DTOP_BLENDTEXTUREALPHA;
pdwTextureStageState_0[D3DTSS_COLORARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
pdwTextureStageState_0[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG2;
pdwTextureStageState_0[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
pdwTextureStageState_1[D3DTSS_COLOROP] = D3DTOP_DISABLE;
break;
case D3DTBLEND_ADD:
pdwTextureStageState_0[D3DTSS_COLOROP] = D3DTOP_ADD;
pdwTextureStageState_0[D3DTSS_COLORARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_COLORARG2] = D3DTA_DIFFUSE;
pdwTextureStageState_0[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG2;
pdwTextureStageState_0[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
pdwTextureStageState_0[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE;
pdwTextureStageState_1[D3DTSS_COLOROP] = D3DTOP_DISABLE;
break;
default:
DISPDBG((ERRLVL,"ERROR: Unknown texture blend!"));
// This needs to be flagged here, because we don't know
// what effect it is meant to have on the TSS stuff.
SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_TEXTUREMAG:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREMAG = 0x%x",dwRSVal));
switch(dwRSVal)
{
case D3DFILTER_NEAREST:
case D3DFILTER_MIPNEAREST:
pdwTextureStageState_0[D3DTSS_MAGFILTER] = D3DTFG_POINT;
break;
case D3DFILTER_LINEAR:
case D3DFILTER_LINEARMIPLINEAR:
case D3DFILTER_MIPLINEAR:
pdwTextureStageState_0[D3DTSS_MAGFILTER] = D3DTFG_LINEAR;
break;
default:
DISPDBG((ERRLVL,"ERROR: Unknown MAG filter!"));
break;
}
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_TEXTUREMIN:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREMIN = 0x%x",dwRSVal));
switch(dwRSVal)
{
case D3DFILTER_NEAREST:
pdwTextureStageState_0[D3DTSS_MINFILTER] = D3DTFN_POINT;
pdwTextureStageState_0[D3DTSS_MIPFILTER] = D3DTFP_NONE;
break;
case D3DFILTER_MIPNEAREST:
pdwTextureStageState_0[D3DTSS_MINFILTER] = D3DTFN_POINT;
pdwTextureStageState_0[D3DTSS_MIPFILTER] = D3DTFP_POINT;
break;
case D3DFILTER_LINEARMIPNEAREST:
pdwTextureStageState_0[D3DTSS_MINFILTER] = D3DTFN_POINT;
pdwTextureStageState_0[D3DTSS_MIPFILTER] = D3DTFP_LINEAR;
break;
case D3DFILTER_LINEAR:
pdwTextureStageState_0[D3DTSS_MINFILTER] = D3DTFN_LINEAR;
pdwTextureStageState_0[D3DTSS_MIPFILTER] = D3DTFP_NONE;
break;
case D3DFILTER_MIPLINEAR:
pdwTextureStageState_0[D3DTSS_MINFILTER] = D3DTFN_LINEAR;
pdwTextureStageState_0[D3DTSS_MIPFILTER] = D3DTFP_POINT;
break;
case D3DFILTER_LINEARMIPLINEAR:
pdwTextureStageState_0[D3DTSS_MINFILTER] = D3DTFN_LINEAR;
pdwTextureStageState_0[D3DTSS_MIPFILTER] = D3DTFP_LINEAR;
break;
default:
DISPDBG((ERRLVL,"ERROR: Unknown MIN filter!"));
break;
}
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_WRAPU:
// map legacy WRAPU state through to controls for tex coord 0
DISPDBG((DBGLVL, "SET D3DRS_WRAPU = 0x%x",dwRSVal));
pContext->RenderStates[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
pContext->RenderStates[D3DRENDERSTATE_WRAP0] |= ((dwRSVal) ? D3DWRAP_U : 0);
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_WRAPV:
// map legacy WRAPV state through to controls for tex coord 0
DISPDBG((DBGLVL, "SET D3DRS_WRAPV = 0x%x",dwRSVal));
pContext->RenderStates[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
pContext->RenderStates[D3DRENDERSTATE_WRAP0] |= ((dwRSVal) ? D3DWRAP_V : 0);
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_TEXTUREADDRESS:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREADDRESS = 0x%x",dwRSVal));
pdwTextureStageState_0[D3DTSS_ADDRESS] =
pdwTextureStageState_0[D3DTSS_ADDRESSU] =
pdwTextureStageState_0[D3DTSS_ADDRESSV] = dwRSVal;
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_TEXTUREADDRESSU:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREADDRESSU = 0x%x",dwRSVal));
pdwTextureStageState_0[D3DTSS_ADDRESSU] = dwRSVal;
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_TEXTUREADDRESSV:
DISPDBG((DBGLVL, "SET D3DRS_TEXTUREADDRESSV = 0x%x",dwRSVal));
pdwTextureStageState_0[D3DTSS_ADDRESSV] = dwRSVal;
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_MIPMAPLODBIAS:
DISPDBG((DBGLVL, "SET D3DRS_MIPMAPLODBIAS = 0x%x",dwRSVal));
pdwTextureStageState_0[D3DTSS_MIPMAPLODBIAS] = dwRSVal;
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_BORDERCOLOR:
DISPDBG((DBGLVL, "SET D3DRS_BORDERCOLOR = 0x%x",dwRSVal));
pdwTextureStageState_0[D3DTSS_BORDERCOLOR] = dwRSVal;
DIRTY_TEXTURE(pContext);
break;
case D3DRENDERSTATE_STIPPLEPATTERN00:
case D3DRENDERSTATE_STIPPLEPATTERN01:
case D3DRENDERSTATE_STIPPLEPATTERN02:
case D3DRENDERSTATE_STIPPLEPATTERN03:
case D3DRENDERSTATE_STIPPLEPATTERN04:
case D3DRENDERSTATE_STIPPLEPATTERN05:
case D3DRENDERSTATE_STIPPLEPATTERN06:
case D3DRENDERSTATE_STIPPLEPATTERN07:
case D3DRENDERSTATE_STIPPLEPATTERN08:
case D3DRENDERSTATE_STIPPLEPATTERN09:
case D3DRENDERSTATE_STIPPLEPATTERN10:
case D3DRENDERSTATE_STIPPLEPATTERN11:
case D3DRENDERSTATE_STIPPLEPATTERN12:
case D3DRENDERSTATE_STIPPLEPATTERN13:
case D3DRENDERSTATE_STIPPLEPATTERN14:
case D3DRENDERSTATE_STIPPLEPATTERN15:
case D3DRENDERSTATE_STIPPLEPATTERN16:
case D3DRENDERSTATE_STIPPLEPATTERN17:
case D3DRENDERSTATE_STIPPLEPATTERN18:
case D3DRENDERSTATE_STIPPLEPATTERN19:
case D3DRENDERSTATE_STIPPLEPATTERN20:
case D3DRENDERSTATE_STIPPLEPATTERN21:
case D3DRENDERSTATE_STIPPLEPATTERN22:
case D3DRENDERSTATE_STIPPLEPATTERN23:
case D3DRENDERSTATE_STIPPLEPATTERN24:
case D3DRENDERSTATE_STIPPLEPATTERN25:
case D3DRENDERSTATE_STIPPLEPATTERN26:
case D3DRENDERSTATE_STIPPLEPATTERN27:
case D3DRENDERSTATE_STIPPLEPATTERN28:
case D3DRENDERSTATE_STIPPLEPATTERN29:
case D3DRENDERSTATE_STIPPLEPATTERN30:
case D3DRENDERSTATE_STIPPLEPATTERN31:
DISPDBG((DBGLVL, "SET D3DRS_STIPPLEPATTERN 2%d = 0x%x",
dwRSType - D3DRENDERSTATE_STIPPLEPATTERN00,
dwRSVal));
pContext->CurrentStipple
[(dwRSType - D3DRENDERSTATE_STIPPLEPATTERN00)] = dwRSVal;
if (!(*pFlags & SURFACE_ALPHASTIPPLE))
{
// Flat-Stippled Alpha is not on, so use the current stipple pattern
SEND_P3_DATA_OFFSET(AreaStipplePattern0,
(DWORD)dwRSVal, dwRSType - D3DRENDERSTATE_STIPPLEPATTERN00);
}
break;
case D3DRENDERSTATE_ROP2:
DISPDBG((DBGLVL, "SET D3DRS_ROP2 = 0x%x",dwRSVal));
NOT_HANDLED;
break;
case D3DRENDERSTATE_PLANEMASK:
DISPDBG((DBGLVL, "SET D3DRS_PLANEMASK = 0x%x",dwRSVal));
SEND_P3_DATA(FBHardwareWriteMask, (DWORD)dwRSVal);
break;
case D3DRENDERSTATE_MONOENABLE:
DISPDBG((DBGLVL, "SET D3DRS_MONOENABLE = 0x%x", dwRSVal));
if (dwRSVal)
{
*pFlags |= SURFACE_MONO;
}
else
{
*pFlags &= ~SURFACE_MONO;
}
break;
case D3DRENDERSTATE_SUBPIXEL:
DISPDBG((DBGLVL, "SET D3DRS_SUBPIXEL = 0x%x", dwRSVal));
NOT_HANDLED;
break;
case D3DRENDERSTATE_SUBPIXELX:
DISPDBG((DBGLVL, "SET D3DRS_SUBPIXELX = 0x%x", dwRSVal));
NOT_HANDLED;
break;
case D3DRENDERSTATE_STIPPLEENABLE:
DISPDBG((DBGLVL, "SET D3DRS_STIPPLEENABLE = 0x%x", dwRSVal));
if (dwRSVal)
{
if (!(*pFlags & SURFACE_ALPHASTIPPLE))
{
RENDER_AREA_STIPPLE_ENABLE(pContext->RenderCommand);
}
pContext->bKeptStipple = TRUE;
}
else
{
RENDER_AREA_STIPPLE_DISABLE(pContext->RenderCommand);
pContext->bKeptStipple = FALSE;
}
break;
case D3DRENDERSTATE_COLORKEYENABLE:
DISPDBG((DBGLVL, "SET D3DRS_COLORKEYENABLE = 0x%x",dwRSVal));
DIRTY_TEXTURE(pContext);
DIRTY_ALPHATEST(pContext);
DIRTY_PIPELINEORDER(pContext);
DIRTY_OPTIMIZE_ALPHA(pContext);
break;
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// The default case handles any other unknown renderstate
//----------------------------------------------------------------------
//----------------------------------------------------------------------
default:
// There are a few states that we just don't understand.
DISPDBG((WRNLVL, "_D3D_ST_ProcessOneRenderState"
" Unhandled opcode = %d", dwRSType));
//SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
break;
}
// Commit DMA Buffer
P3_DMA_COMMIT_BUFFER();
DBG_EXIT(_D3D_ST_ProcessOneRenderState,0);
return DD_OK;
} // _D3D_ST_ProcessOneRenderState
//-----------------------------------------------------------------------------
//
// _D3D_ST_ProcessRenderStates
//
// Updates the context's renderstates processing an array of D3DSTATE
// structures with dwStateCount elements in it. bDoOverride indicates
// if legacy state overrides are to be taken into account.
//-----------------------------------------------------------------------------
DWORD
_D3D_ST_ProcessRenderStates(
P3_D3DCONTEXT* pContext,
DWORD dwStateCount,
D3DSTATE *pState,
BOOL bDoOverride)
{
DWORD dwCurrState;
DBG_ENTRY(_D3D_ST_ProcessRenderStates);
DISPDBG((DBGLVL, "_D3D_ST_ProcessRenderStates: "
"Valid Context =%08lx, dwStateCount=%d",
pContext, dwStateCount));
for (dwCurrState = 0; dwCurrState < dwStateCount; dwCurrState++, pState++)
{
DWORD dwRSType = (DWORD) pState->drstRenderStateType;
DWORD dwRSVal = pState->dwArg[0];
// Override states for legacy API apps
if (bDoOverride)
{
// Make sure the override is within the valid range
if ((dwRSType >= (D3DSTATE_OVERRIDE_BIAS + MAX_STATE)) ||
(dwRSType < 1))
{
DISPDBG((ERRLVL, "_D3D_ST_ProcessRenderStates: "
"Invalid render state %d",
dwRSType));
continue;
}
if (IS_OVERRIDE(dwRSType))
{
DWORD override = GET_OVERRIDE(dwRSType);
if (dwRSVal)
{
DISPDBG((DBGLVL, "_D3D_ST_ProcessRenderStates: "
"setting override for state %d",
override));
STATESET_SET(pContext->overrides, override);
}
else
{
DISPDBG((DBGLVL, "_D3D_ST_ProcessRenderStates: "
"clearing override for state %d",
override));
STATESET_CLEAR(pContext->overrides, override);
}
continue;
}
if (STATESET_ISSET(pContext->overrides, dwRSType))
{
DISPDBG((DBGLVL, "_D3D_ST_ProcessRenderStates: "
"state %d is overridden, ignoring",
dwRSType));
continue;
}
}
// Make sure the render state is within the valid range
if ((dwRSType >= MAX_STATE) || (dwRSType < 1))
{
continue;
}
#if DX7_D3DSTATEBLOCKS
if (pContext->bStateRecMode)
{
// Record this render state into the
// current state set being recorded
_D3D_SB_RecordStateSetRS(pContext, dwRSType, dwRSVal);
}
else
#endif //DX7_D3DSTATEBLOCKS
{
// Process the next render state
_D3D_ST_ProcessOneRenderState(pContext, dwRSType, dwRSVal);
}
}
DBG_EXIT(_D3D_ST_ProcessRenderStates,0);
return DD_OK;
} // _D3D_ST_ProcessRenderStates
//-----------------------------------------------------------------------------
//
// _D3D_ST_RealizeHWStateChanges
//
// Verifies if there are pending hardware render state changes to set up,
// before proceeding to rasterize/render primitives. This might be convenient
// if the combined setting of some renderstates allows us to optimize the
// hardware setup in some way.
//
//-----------------------------------------------------------------------------
BOOL
_D3D_ST_RealizeHWStateChanges(
P3_D3DCONTEXT* pContext)
{
P3_THUNKEDDATA *pThisDisplay;
DBG_ENTRY(_D3D_ST_RealizeHWStateChanges);
pThisDisplay = pContext->pThisDisplay;
// Check if a flip or a mode change have happened. If so, we will
// need to setup the render target registers before doing any
// new rendering
if (pContext->ModeChangeCount != pThisDisplay->ModeChangeCount)
{
pContext->ModeChangeCount = pThisDisplay->ModeChangeCount;
pThisDisplay->bFlippedSurface = TRUE;
}
if (pThisDisplay->bFlippedSurface)
{
DIRTY_RENDER_OFFSETS(pContext);
}
// If there are any pending renderstates to process, do so
if ( pContext->dwDirtyFlags )
{
// Now setup any pending hardware state necessary to correctly
// render our primitives
__ST_HandleDirtyP3State( pThisDisplay, pContext);
// Mark the context as up to date
pContext->dwDirtyFlags = 0;
// Verify that the working set textures are valid so we may proceed
// with rendering. Otherwise we will abort the attempt to render
// anything
if (!pContext->bTextureValid)
{
DISPDBG((ERRLVL,"ERROR: _D3D_ST_RealizeHWStateChanges:"
"Invalid Texture Handle, not rendering"));
// re-dirty the texture setup so that we may try again later
pContext->dwDirtyFlags |= CONTEXT_DIRTY_TEXTURE;
DBG_EXIT(_D3D_ST_RealizeHWStateChanges,1);
return FALSE;
}
}
DBG_EXIT(_D3D_ST_RealizeHWStateChanges,0);
return TRUE;
} // _D3D_ST_RealizeHWStateChanges