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