/******************************Module*Header**********************************\ * * ******************* * * D3D SAMPLE CODE * * ******************* * * Module Name: d3dstate.c * * Contains code to translate D3D renderstates and texture stage * states into hardware specific settings. * * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved. \*****************************************************************************/ #include "precomp.h" #include "d3dhw.h" #include "d3dcntxt.h" #include "d3ddelta.h" #include "d3dtxman.h" #define ALLOC_TAG ALLOC_TAG_SD2P //----------------------------------------------------------------------------- // // void __SelectFVFTexCoord // // This utility function sets the correct texture offset depending on the // texturing coordinate set wished to be used from the FVF vertexes // //----------------------------------------------------------------------------- void __SelectFVFTexCoord(LPP2FVFOFFSETS lpP2FVFOff, DWORD dwTexCoord) { DBG_D3D((10,"Entering __SelectFVFTexCoord")); lpP2FVFOff->dwTexOffset = lpP2FVFOff->dwTexBaseOffset + dwTexCoord * 2 * sizeof(D3DVALUE); // verify the requested texture coordinate doesn't exceed the FVF // vertex structure provided , if so go down to set 0 as a // crash-avoiding alternative if (lpP2FVFOff->dwTexOffset >= lpP2FVFOff->dwStride) lpP2FVFOff->dwTexOffset = lpP2FVFOff->dwTexBaseOffset; DBG_D3D((10,"Exiting __SelectFVFTexCoord")); } // __SelectFVFTexCoord //----------------------------------------------------------------------------- // // HRESULT __HWPreProcessTSS // // Processes the state changes that must be done as soon as they arrive // //----------------------------------------------------------------------------- void __HWPreProcessTSS(PERMEDIA_D3DCONTEXT *pContext, DWORD dwStage, DWORD dwState, DWORD dwValue) { DBG_D3D((10,"Entering __HWPreProcessTSS")); if (D3DTSS_ADDRESS == dwState) { pContext->TssStates[D3DTSS_ADDRESSU] = dwValue; pContext->TssStates[D3DTSS_ADDRESSV] = dwValue; } else if (D3DTSS_TEXTUREMAP == dwState && 0 != dwValue) { PPERMEDIA_D3DTEXTURE pTexture=TextureHandleToPtr(dwValue, pContext); if (CHECK_D3DSURFACE_VALIDITY(pTexture) && (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)) { TextureCacheManagerIncNumTexturesSet(pContext->pTextureManager); if (pTexture->m_dwHeapIndex) TextureCacheManagerIncNumSetTexInVid(pContext->pTextureManager); } } DBG_D3D((10,"Exiting __HWPreProcessTSS")); } // __HWPreProcessTSS //----------------------------------------------------------------------------- // // HRESULT __HWSetupStageStates // // Processes the state changes related to the DX6 texture stage states in the // current rendering context // //----------------------------------------------------------------------------- HRESULT WINAPI __HWSetupStageStates(PERMEDIA_D3DCONTEXT *pContext, LPP2FVFOFFSETS lpP2FVFOff) { __P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs; DWORD *pFlags = &pContext->Hdr.Flags; PERMEDIA_DEFS(pContext->ppdev); DBG_D3D((10,"Entering __HWSetupStageStates")); // If we are to texture map our primitives if (pContext->TssStates[D3DTSS_TEXTUREMAP]) { DWORD dwMag = pContext->TssStates[D3DTSS_MAGFILTER]; DWORD dwMin = pContext->TssStates[D3DTSS_MINFILTER]; DWORD dwMip = pContext->TssStates[D3DTSS_MIPFILTER]; DWORD dwCop = pContext->TssStates[D3DTSS_COLOROP]; DWORD dwCa1 = pContext->TssStates[D3DTSS_COLORARG1]; DWORD dwCa2 = pContext->TssStates[D3DTSS_COLORARG2]; DWORD dwAop = pContext->TssStates[D3DTSS_ALPHAOP]; DWORD dwAa1 = pContext->TssStates[D3DTSS_ALPHAARG1]; DWORD dwAa2 = pContext->TssStates[D3DTSS_ALPHAARG2]; DWORD dwTau = pContext->TssStates[D3DTSS_ADDRESSU]; DWORD dwTav = pContext->TssStates[D3DTSS_ADDRESSV]; DWORD dwTxc = pContext->TssStates[D3DTSS_TEXCOORDINDEX]; DBG_D3D((6,"Setting up w TSS:" "dwCop=%x dwCa1=%x dwCa2=%x dwAop=%x dwAa1=%x dwAa2=%x " "dwMag=%x dwMin=%x dwMip=%x dwTau=%x dwTav=%x dwTxc=%x", dwCop, dwCa1, dwCa2, dwAop, dwAa1, dwAa2, dwMag, dwMin, dwMip, dwTau, dwTav, dwTxc)); // Choose texture coord to use __SelectFVFTexCoord( lpP2FVFOff, dwTxc); // Current is the same as diffuse in stage 0 if (dwCa2 == D3DTA_CURRENT) dwCa2 = D3DTA_DIFFUSE; if (dwAa2 == D3DTA_CURRENT) dwAa2 = D3DTA_DIFFUSE; // Check if we need to disable texturing if (dwCop == D3DTOP_DISABLE || (dwCop == D3DTOP_SELECTARG2 && dwCa2 == D3DTA_DIFFUSE && dwAop == D3DTOP_SELECTARG2 && dwAa2 == D3DTA_DIFFUSE)) { //Please don't clear pContext->TssStates[D3DTSS_TEXTUREMAP] though pContext->CurrentTextureHandle = 0; DBG_D3D((10,"Exiting __HWSetupStageStates , texturing disabled")); return DD_OK; } // setup the address mode switch (dwTau) { case D3DTADDRESS_CLAMP: pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_CLAMP; break; case D3DTADDRESS_WRAP: pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_REPEAT; break; case D3DTADDRESS_MIRROR: pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_MIRROR; break; default: DBG_D3D((2, "Illegal value passed to TSS U address mode = %d" ,dwTau)); pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_REPEAT; break; } switch (dwTav) { case D3DTADDRESS_CLAMP: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_CLAMP; break; case D3DTADDRESS_WRAP: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_REPEAT; break; case D3DTADDRESS_MIRROR: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_MIRROR; break; default: DBG_D3D((2, "Illegal value passed to TSS V address mode = %d" ,dwTav)); pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_REPEAT; break; } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(TextureReadMode, pSoftPermedia->TextureReadMode); COMMITDMAPTR(); // Enable-disable wrapping flags for U & V if (pContext->dwWrap[dwTxc] & D3DWRAPCOORD_0) { *pFlags |= CTXT_HAS_WRAPU_ENABLED; } else { *pFlags &= ~CTXT_HAS_WRAPU_ENABLED; } if (pContext->dwWrap[dwTxc] & D3DWRAPCOORD_1) { *pFlags |= CTXT_HAS_WRAPV_ENABLED; } else { *pFlags &= ~CTXT_HAS_WRAPV_ENABLED; } // Setup the equivalent texture filtering state if (dwMip == D3DTFP_NONE) { // We can only take care of magnification filtering on the P2 if (dwMag == D3DTFG_LINEAR) { pContext->bMagFilter = TRUE; // D3DFILTER_LINEAR; } else if (dwMag == D3DTFG_POINT) { pContext->bMagFilter = FALSE; // D3DFILTER_NEAREST; } } else if (dwMip == D3DTFP_POINT) { if (dwMin == D3DTFN_POINT) { pContext->bMagFilter = FALSE; // D3DFILTER_MIPNEAREST; } else if (dwMin == D3DTFN_LINEAR) { pContext->bMagFilter = TRUE; // D3DFILTER_MIPLINEAR; } } else { // dwMip == D3DTFP_LINEAR if (dwMin == D3DTFN_POINT) { pContext->bMagFilter = TRUE; // D3DFILTER_LINEARMIPNEAREST; } else if (dwMin == D3DTFN_LINEAR) { pContext->bMagFilter = TRUE; // D3DFILTER_LINEARMIPLINEAR; } } // Setup the equivalent texture blending state // Check if we need to decal if ((dwCa1 == D3DTA_TEXTURE && dwCop == D3DTOP_SELECTARG1) && (dwAa1 == D3DTA_TEXTURE && dwAop == D3DTOP_SELECTARG1)) { // D3DTBLEND_COPY; pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_COPY; } // check if we the app modified the TSS for decaling after first // setting it up for modulating via the legacy renderstates // this is a Permedia2 specific optimization. else if ((dwCa1 == D3DTA_TEXTURE && dwCop == D3DTOP_SELECTARG1) && (dwAa1 == D3DTA_TEXTURE && dwAop == D3DTOP_LEGACY_ALPHAOVR)) { // D3DTBLEND_COPY; pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_COPY; } // Check if we need to modulate & pass texture alpha else if ((dwCa2 == D3DTA_DIFFUSE && dwCa1 == D3DTA_TEXTURE) && dwCop == D3DTOP_MODULATE && (dwAa1 == D3DTA_TEXTURE && dwAop == D3DTOP_SELECTARG1)) { // D3DTBLEND_MODULATE; pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_MODULATE; } // Check if we need to modulate & pass diffuse alpha else if ((dwCa2 == D3DTA_DIFFUSE && dwCa1 == D3DTA_TEXTURE) && dwCop == D3DTOP_MODULATE && (dwAa2 == D3DTA_DIFFUSE && dwAop == D3DTOP_SELECTARG2)) { // D3DTBLEND_MODULATE; pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_MODULATE; } // Check if we need to do legacy modulate else if ((dwCa2 == D3DTA_DIFFUSE && dwCa1 == D3DTA_TEXTURE) && dwCop == D3DTOP_MODULATE && (dwAa1 == D3DTA_TEXTURE && dwAop == D3DTOP_LEGACY_ALPHAOVR)) { // D3DTBLEND_MODULATE; pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_MODULATE; } // Check if we need to decal alpha else if ((dwCa2 == D3DTA_DIFFUSE && dwCa1 == D3DTA_TEXTURE) && dwCop == D3DTOP_BLENDTEXTUREALPHA && (dwAa2 == D3DTA_DIFFUSE && dwAop == D3DTOP_SELECTARG2)) { // D3DTBLEND_DECALALPHA; pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_DECAL; } // Check if we need to modulate alpha else if ((dwCa2 == D3DTA_DIFFUSE && dwCa1 == D3DTA_TEXTURE) && dwCop == D3DTOP_MODULATE && (dwAa2 == D3DTA_DIFFUSE && dwAa1 == D3DTA_TEXTURE) && dwAop == D3DTOP_MODULATE) { // D3DTBLEND_MODULATEALPHA; pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_MODULATE; } else { DBG_D3D((0,"Trying to setup a state we don't understand!")); } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(TextureColorMode, pSoftPermedia->TextureColorMode); COMMITDMAPTR(); pContext->CurrentTextureHandle = pContext->TssStates[D3DTSS_TEXTUREMAP]; } else // No texturing pContext->CurrentTextureHandle = 0; DIRTY_TEXTURE; DBG_D3D((10,"Exiting __HWSetupStageStates")); return DD_OK; } //__HWSetupStageStates //----------------------------------------------------------------------------- // // void __HandleDirtyPermediaState // // Setup of context that is deferred until just before // rendering an actual rendering primitive // //----------------------------------------------------------------------------- void __HandleDirtyPermediaState(PPDev ppdev, PERMEDIA_D3DCONTEXT* pContext, LPP2FVFOFFSETS lpP2FVFOff) { __P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs; PERMEDIA_DEFS(pContext->ppdev); ULONG AlphaBlendSend; DBG_D3D((10,"Entering __HandleDirtyPermediaState")); // We need to keep this ordering of evaluation on the P2 // --------------Have the texture or the stage states changed ? ----------- if (pContext->dwDirtyFlags & CONTEXT_DIRTY_TEXTURE) { DBG_D3D((4,"preparing to handle CONTEXT_DIRTY_TEXTURE")); // Choose between legacy Texture Handle or TSS if (pContext->dwDirtyFlags & CONTEXT_DIRTY_MULTITEXTURE) { pContext->dwDirtyFlags &= ~CONTEXT_DIRTY_MULTITEXTURE; //Setup TSS state AND textures if ( SUCCEEDED(__HWSetupStageStates(pContext, lpP2FVFOff)) ) { // if this FVF has no tex coordinates at all disable texturing if (lpP2FVFOff->dwTexBaseOffset == 0) { pContext->CurrentTextureHandle = 0; DBG_D3D((2,"No texture coords present in FVF " "to texture map primitives")); } } else { pContext->CurrentTextureHandle = 0; DBG_D3D((0,"TSS Setup failed")); } } else { // select default texture coordinate index __SelectFVFTexCoord( lpP2FVFOff, 0); } } // --------------Has the state of the LB changed ? ------------------------ if (pContext->dwDirtyFlags & CONTEXT_DIRTY_ZBUFFER) { DBG_D3D((4,"CONTEXT_DIRTY_ZBUFFER handled")); pContext->dwDirtyFlags &= ~CONTEXT_DIRTY_ZBUFFER; if ((pContext->Hdr.Flags & CTXT_HAS_ZBUFFER_ENABLED) && (pContext->ZBufferHandle)) { if (pContext->Hdr.Flags & CTXT_HAS_ZWRITE_ENABLED) { if (__PERMEDIA_DEPTH_COMPARE_MODE_NEVER == (int)pSoftPermedia->DepthMode.CompareMode) { pSoftPermedia->LBReadMode.ReadDestinationEnable = __PERMEDIA_DISABLE; pSoftPermedia->LBWriteMode.WriteEnable = __PERMEDIA_DISABLE; } else { pSoftPermedia->LBReadMode.ReadDestinationEnable = __PERMEDIA_ENABLE; pSoftPermedia->LBWriteMode.WriteEnable = __PERMEDIA_ENABLE; } pSoftPermedia->DepthMode.WriteMask = __PERMEDIA_ENABLE; } else { pSoftPermedia->LBReadMode.ReadDestinationEnable = __PERMEDIA_ENABLE; pSoftPermedia->LBWriteMode.WriteEnable = __PERMEDIA_DISABLE; pSoftPermedia->DepthMode.WriteMask = __PERMEDIA_DISABLE; } // We are Z Buffering // Enable Z test pSoftPermedia->DepthMode.UnitEnable = __PERMEDIA_ENABLE; // Tell delta we are Z Buffering. pSoftPermedia->DeltaMode.DepthEnable = 1; } else { // We are NOT Z Buffering // Disable Writes pSoftPermedia->LBWriteMode.WriteEnable = __PERMEDIA_DISABLE; // Disable Z test pSoftPermedia->DepthMode.UnitEnable = __PERMEDIA_DISABLE; pSoftPermedia->DepthMode.WriteMask = __PERMEDIA_DISABLE; // No reads, no writes pSoftPermedia->LBReadMode.ReadDestinationEnable = __PERMEDIA_DISABLE; // Tell delta we aren't Z Buffering. pSoftPermedia->DeltaMode.DepthEnable = 0; } if (__PERMEDIA_ENABLE == pSoftPermedia->StencilMode.UnitEnable) { pSoftPermedia->LBReadMode.ReadDestinationEnable = __PERMEDIA_ENABLE; pSoftPermedia->LBWriteMode.WriteEnable = __PERMEDIA_ENABLE; } RESERVEDMAPTR(7); COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); COPY_PERMEDIA_DATA(StencilMode, pSoftPermedia->StencilMode); COPY_PERMEDIA_DATA(StencilData, pSoftPermedia->StencilData); COPY_PERMEDIA_DATA(Window, pSoftPermedia->Window); COPY_PERMEDIA_DATA(DepthMode, pSoftPermedia->DepthMode); COPY_PERMEDIA_DATA(LBReadMode, pSoftPermedia->LBReadMode); COPY_PERMEDIA_DATA(LBWriteMode, pSoftPermedia->LBWriteMode); COMMITDMAPTR(); } // if CONTEXT_DIRTY_ZBUFFER // ----------------Has the alphablend type changed ? ---------------------- if (pContext->dwDirtyFlags & CONTEXT_DIRTY_ALPHABLEND) { // Only clear when we have an alphablend dirty context pContext->FakeBlendNum &= ~FAKE_ALPHABLEND_ONE_ONE; pContext->dwDirtyFlags &= ~CONTEXT_DIRTY_ALPHABLEND; // Verify that requested blend mode is HW supported DWORD dwBlendMode; dwBlendMode = (((DWORD)pSoftPermedia->AlphaBlendMode.SourceBlend) | ((DWORD)pSoftPermedia->AlphaBlendMode.DestinationBlend) << 4); DBG_D3D((4,"CONTEXT_DIRTY_ALPHABLEND handled: Blend mode = %08lx", dwBlendMode)); switch (dwBlendMode) { // In this case, we set the bit to the QuickDraw mode case __PERMEDIA_BLENDOP_ONE_AND_INVSRCALPHA: DBG_D3D((4,"Blend Operation is PreMult")); pSoftPermedia->AlphaBlendMode.BlendType = 1; break; // This is the standard blend case __PERMEDIA_BLENDOP_SRCALPHA_AND_INVSRCALPHA: DBG_D3D((4,"Blend Operation is Blend")); pSoftPermedia->AlphaBlendMode.BlendType = 0; break; case ((__PERMEDIA_BLEND_FUNC_ZERO << 4) | __PERMEDIA_BLEND_FUNC_SRC_ALPHA): // we substitute the SrcBlend = SrcAlpha DstBlend = 1 // with the 1,0 mode since we really dont' support // it, just so apps perform reasonably pSoftPermedia->AlphaBlendMode.AlphaBlendEnable = 0; case ((__PERMEDIA_BLEND_FUNC_ONE << 4) | __PERMEDIA_BLEND_FUNC_ZERO): case __PERMEDIA_BLENDOP_ONE_AND_ZERO: // This is code for 'no blending' DBG_D3D((4,"Blend Operation is validly None")); break; case ((__PERMEDIA_BLEND_FUNC_ONE << 4) | __PERMEDIA_BLEND_FUNC_SRC_ALPHA): // we substitute the SrcBlend = SrcAlpha DstBlend = 1 // with the 1,1 mode since we really dont' support // it, just so apps perform reasonably case __PERMEDIA_BLENDOP_ONE_AND_ONE: DBG_D3D((4,"BlendOperation is 1 Source, 1 Dest")); pSoftPermedia->AlphaBlendMode.BlendType = 1; pContext->FakeBlendNum |= FAKE_ALPHABLEND_ONE_ONE; break; default: DBG_D3D((2,"Blend Operation is invalid! BlendOp == %x", dwBlendMode)); // This is a fallback blending mode dwBlendMode = __PERMEDIA_BLENDOP_ONE_AND_ZERO; break; } if ((pContext->Hdr.Flags & CTXT_HAS_ALPHABLEND_ENABLED) && (dwBlendMode != __PERMEDIA_BLENDOP_ONE_AND_ZERO)) { // Set the AlphaBlendMode register on Permedia pSoftPermedia->AlphaBlendMode.AlphaBlendEnable = 1; // Turn on destination read in the FBReadMode register pSoftPermedia->FBReadMode.ReadDestinationEnable = 1; } else { // Set the AlphaBlendMode register on Permedia pSoftPermedia->AlphaBlendMode.AlphaBlendEnable = 0; // Turn off the destination read in FbReadMode register pSoftPermedia->FBReadMode.ReadDestinationEnable = 0; // if not sending alpha, turn alpha to 1 RESERVEDMAPTR(1); SEND_PERMEDIA_DATA(AStart, PM_BYTE_COLOR(0xFF)); COMMITDMAPTR(); } AlphaBlendSend = ((DWORD)*(DWORD*)(&pSoftPermedia->AlphaBlendMode)); // Insert changes in blend mode for unsupported blend operations // in this function if (FAKE_ALPHABLEND_ONE_ONE & pContext->FakeBlendNum) { AlphaBlendSend &= 0xFFFFFF01; AlphaBlendSend |= (__PERMEDIA_BLENDOP_ONE_AND_INVSRCALPHA << 1); } RESERVEDMAPTR(2); COPY_PERMEDIA_DATA(FBReadMode, pSoftPermedia->FBReadMode); COPY_PERMEDIA_DATA(AlphaBlendMode, AlphaBlendSend); COMMITDMAPTR(); } // --------------------Has the texture handle changed ? ------------------- if (pContext->dwDirtyFlags & CONTEXT_DIRTY_TEXTURE) { pContext->dwDirtyFlags &= ~CONTEXT_DIRTY_TEXTURE; DBG_D3D((4,"CONTEXT_DIRTY_TEXTURE handled")); if (pContext->CurrentTextureHandle == 0) DisableTexturePermedia(pContext); else EnableTexturePermedia(pContext); } DBG_D3D((10,"Exiting __HandleDirtyPermediaState")); } // __HandleDirtyPermediaState //----------------------------------------------------------------------------- // // void __MapRS_Into_TSS0 // // Map Renderstate changes into the corresponding change in the Texture Stage // State #0 . // //----------------------------------------------------------------------------- void __MapRS_Into_TSS0(PERMEDIA_D3DCONTEXT* pContext, DWORD dwRSType, DWORD dwRSVal) { DBG_D3D((10,"Entering __MapRS_Into_TSS0")); // Process each specific renderstate switch (dwRSType) { case D3DRENDERSTATE_TEXTUREHANDLE: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_TEXTUREMAP] = dwRSVal; break; case D3DRENDERSTATE_TEXTUREMAPBLEND: switch (dwRSVal) { case D3DTBLEND_DECALALPHA: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_COLOROP] = D3DTOP_BLENDTEXTUREALPHA; pContext->TssStates[D3DTSS_COLORARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_COLORARG2] = D3DTA_DIFFUSE; pContext->TssStates[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG2; pContext->TssStates[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE; break; case D3DTBLEND_MODULATE: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_COLOROP] = D3DTOP_MODULATE; pContext->TssStates[D3DTSS_COLORARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_COLORARG2] = D3DTA_DIFFUSE; // a special legacy alpha operation is called for // that depends on the format of the texture pContext->TssStates[D3DTSS_ALPHAOP] = D3DTOP_LEGACY_ALPHAOVR; pContext->TssStates[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE; break; case D3DTBLEND_MODULATEALPHA: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_COLOROP] = D3DTOP_MODULATE; pContext->TssStates[D3DTSS_COLORARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_COLORARG2] = D3DTA_DIFFUSE; pContext->TssStates[D3DTSS_ALPHAOP] = D3DTOP_MODULATE; pContext->TssStates[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;; pContext->TssStates[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE; break; case D3DTBLEND_COPY: case D3DTBLEND_DECAL: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_COLOROP] = D3DTOP_SELECTARG1; pContext->TssStates[D3DTSS_COLORARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1; pContext->TssStates[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE; break; case D3DTBLEND_ADD: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_COLOROP] = D3DTOP_ADD; pContext->TssStates[D3DTSS_COLORARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_COLORARG2] = D3DTA_DIFFUSE; pContext->TssStates[D3DTSS_ALPHAOP] = D3DTOP_SELECTARG2; pContext->TssStates[D3DTSS_ALPHAARG1] = D3DTA_TEXTURE; pContext->TssStates[D3DTSS_ALPHAARG2] = D3DTA_DIFFUSE; } break; case D3DRENDERSTATE_BORDERCOLOR: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_BORDERCOLOR] = dwRSVal; break; case D3DRENDERSTATE_MIPMAPLODBIAS: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_MIPMAPLODBIAS] = dwRSVal; break; case D3DRENDERSTATE_ANISOTROPY: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_MAXANISOTROPY] = dwRSVal; break; case D3DRENDERSTATE_TEXTUREADDRESS: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_ADDRESSU] = pContext->TssStates[D3DTSS_ADDRESSV] = dwRSVal; break; case D3DRENDERSTATE_TEXTUREADDRESSU: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_ADDRESSU] = dwRSVal; break; case D3DRENDERSTATE_TEXTUREADDRESSV: //Mirror texture related render states into TSS stage 0 pContext->TssStates[D3DTSS_ADDRESSV] = dwRSVal; break; case D3DRENDERSTATE_TEXTUREMAG: switch(dwRSVal) { case D3DFILTER_NEAREST: pContext->TssStates[D3DTSS_MAGFILTER] = D3DTFG_POINT; break; case D3DFILTER_LINEAR: case D3DFILTER_MIPLINEAR: case D3DFILTER_MIPNEAREST: case D3DFILTER_LINEARMIPNEAREST: case D3DFILTER_LINEARMIPLINEAR: pContext->TssStates[D3DTSS_MAGFILTER] = D3DTFG_LINEAR; break; default: break; } break; case D3DRENDERSTATE_TEXTUREMIN: switch(dwRSVal) { case D3DFILTER_NEAREST: pContext->TssStates[D3DTSS_MINFILTER] = D3DTFN_POINT; pContext->TssStates[D3DTSS_MIPFILTER] = D3DTFP_NONE; break; case D3DFILTER_LINEAR: pContext->TssStates[D3DTSS_MINFILTER] = D3DTFN_LINEAR; pContext->TssStates[D3DTSS_MIPFILTER] = D3DTFP_NONE; break; case D3DFILTER_MIPNEAREST: pContext->TssStates[D3DTSS_MINFILTER] = D3DTFN_POINT; pContext->TssStates[D3DTSS_MIPFILTER] = D3DTFP_POINT; break; case D3DFILTER_MIPLINEAR: pContext->TssStates[D3DTSS_MINFILTER] = D3DTFN_LINEAR; pContext->TssStates[D3DTSS_MIPFILTER] = D3DTFP_POINT; break; case D3DFILTER_LINEARMIPNEAREST: pContext->TssStates[D3DTSS_MINFILTER] = D3DTFN_POINT; pContext->TssStates[D3DTSS_MIPFILTER] = D3DTFP_LINEAR; break; case D3DFILTER_LINEARMIPLINEAR: pContext->TssStates[D3DTSS_MINFILTER] = D3DTFN_LINEAR; pContext->TssStates[D3DTSS_MIPFILTER] = D3DTFP_LINEAR; break;; default: break; } break; default: // All other renderstates don't have a corresponding TSS state so // we don't have to worry about mapping them. break; } // switch (dwRSType of renderstate) DBG_D3D((10,"Exiting __MapRS_Into_TSS0")); } // __MapRS_Into_TSS0 //----------------------------------------------------------------------------- // // void __ProcessRenderState // // Handle a single render state change // //----------------------------------------------------------------------------- void __ProcessRenderStates(PERMEDIA_D3DCONTEXT* pContext, DWORD dwRSType, DWORD dwRSVal) { __P2RegsSoftwareCopy* pSoftPermedia = &pContext->Hdr.SoftCopyP2Regs; DWORD* pFlags = &pContext->Hdr.Flags; PERMEDIA_DEFS(pContext->ppdev); DBG_D3D((10,"Entering __ProcessRenderStates")); // Process each specific renderstate switch (dwRSType) { case D3DRENDERSTATE_TEXTUREMAPBLEND: DBG_D3D((8, "ChangeState: Texture Blend Mode 0x%x " "(D3DTEXTUREBLEND)", dwRSVal)); switch (dwRSVal) { case D3DTBLEND_DECALALPHA: pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_DECAL; break; case D3DTBLEND_MODULATE: pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_MODULATE; break; case D3DTBLEND_MODULATEALPHA: pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_MODULATE; break; case D3DTBLEND_COPY: case D3DTBLEND_DECAL: pSoftPermedia->TextureColorMode.ApplicationMode = _P2_TEXTURE_COPY; break; } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(TextureColorMode, pSoftPermedia->TextureColorMode); COMMITDMAPTR(); DIRTY_TEXTURE; // May need to change DDA break; case D3DRENDERSTATE_TEXTUREADDRESS: DBG_D3D((8, "ChangeState: Texture address 0x%x " "(D3DTEXTUREADDRESS)", dwRSVal)); switch (dwRSVal) { case D3DTADDRESS_CLAMP: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_CLAMP; pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_CLAMP; break; case D3DTADDRESS_WRAP: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_REPEAT; pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_REPEAT; break; case D3DTADDRESS_MIRROR: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_MIRROR; pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_MIRROR; break; default: DBG_D3D((2, "Illegal value passed to ChangeState " " D3DRENDERSTATE_TEXTUREADDRESS = %d", dwRSVal)); // set a fallback value pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_REPEAT; pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_REPEAT; break; } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(TextureReadMode, pSoftPermedia->TextureReadMode); COMMITDMAPTR(); break; case D3DRENDERSTATE_TEXTUREADDRESSU: DBG_D3D((8, "ChangeState: Texture address 0x%x " "(D3DTEXTUREADDRESSU)", dwRSVal)); switch (dwRSVal) { case D3DTADDRESS_CLAMP: pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_CLAMP; break; case D3DTADDRESS_WRAP: pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_REPEAT; break; case D3DTADDRESS_MIRROR: pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_MIRROR; break; default: DBG_D3D((2, "Illegal value passed to ChangeState " " D3DRENDERSTATE_TEXTUREADDRESSU = %d", dwRSVal)); // set a fallback value pSoftPermedia->TextureReadMode.SWrapMode = _P2_TEXTURE_REPEAT; break; } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(TextureReadMode, pSoftPermedia->TextureReadMode); COMMITDMAPTR(); break; case D3DRENDERSTATE_TEXTUREADDRESSV: DBG_D3D((8, "ChangeState: Texture address 0x%x " "(D3DTEXTUREADDRESSV)", dwRSVal)); switch (dwRSVal) { case D3DTADDRESS_CLAMP: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_CLAMP; break; case D3DTADDRESS_WRAP: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_REPEAT; break; case D3DTADDRESS_MIRROR: pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_MIRROR; break; default: DBG_D3D((2, "Illegal value passed to ChangeState " " D3DRENDERSTATE_TEXTUREADDRESSV = %d", dwRSVal)); // set a fallback value pSoftPermedia->TextureReadMode.TWrapMode = _P2_TEXTURE_REPEAT; break; } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(TextureReadMode, pSoftPermedia->TextureReadMode); COMMITDMAPTR(); break; case D3DRENDERSTATE_TEXTUREHANDLE: DBG_D3D((8, "ChangeState: Texture Handle 0x%x",dwRSVal)); if (dwRSVal != pContext->CurrentTextureHandle) { pContext->CurrentTextureHandle = dwRSVal; DIRTY_TEXTURE; } break; case D3DRENDERSTATE_ANTIALIAS: DBG_D3D((8, "ChangeState: AntiAlias 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_WRAPU: DBG_D3D((8, "ChangeState: Wrap_U " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal) { *pFlags |= CTXT_HAS_WRAPU_ENABLED; } else { *pFlags &= ~CTXT_HAS_WRAPU_ENABLED; } break; case D3DRENDERSTATE_WRAPV: DBG_D3D((8, "ChangeState: Wrap_V " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal) { *pFlags |= CTXT_HAS_WRAPV_ENABLED; } else { *pFlags &= ~CTXT_HAS_WRAPV_ENABLED; } break; case D3DRENDERSTATE_LINEPATTERN: DBG_D3D((8, "ChangeState: Line Pattern " "(D3DLINEPATTERN) 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_ZWRITEENABLE: DBG_D3D((8, "ChangeState: Z Write Enable " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal != 0) { // Local Buffer Write mode if (!(*pFlags & CTXT_HAS_ZWRITE_ENABLED)) { DBG_D3D((8, " Enabling Z Writes")); *pFlags |= CTXT_HAS_ZWRITE_ENABLED; DIRTY_ZBUFFER; } } else { if (*pFlags & CTXT_HAS_ZWRITE_ENABLED) { DBG_D3D((8, " Disabling Z Writes")); *pFlags &= ~CTXT_HAS_ZWRITE_ENABLED; DIRTY_ZBUFFER; } } break; case D3DRENDERSTATE_ALPHATESTENABLE: DBG_D3D((8, "ChangeState: Alpha Test Enable " "(BOOL) 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_LASTPIXEL: // True for last pixel on lines DBG_D3D((8, "ChangeState: Last Pixel " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal) { *pFlags |= CTXT_HAS_LASTPIXEL_ENABLED; } else { *pFlags &= ~CTXT_HAS_LASTPIXEL_ENABLED; } break; case D3DRENDERSTATE_TEXTUREMAG: DBG_D3D((8, "ChangeState: Texture magnification " "(D3DTEXTUREFILTER) 0x%x",dwRSVal)); switch(dwRSVal) { case D3DFILTER_NEAREST: case D3DFILTER_MIPNEAREST: pContext->bMagFilter = FALSE; pSoftPermedia->TextureReadMode.FilterMode = 0; break; case D3DFILTER_LINEAR: case D3DFILTER_MIPLINEAR: case D3DFILTER_LINEARMIPNEAREST: case D3DFILTER_LINEARMIPLINEAR: pContext->bMagFilter = TRUE; pSoftPermedia->TextureReadMode.FilterMode = 1; break; default: break; } DIRTY_TEXTURE; break; case D3DRENDERSTATE_TEXTUREMIN: DBG_D3D((8, "ChangeState: Texture minification " "(D3DTEXTUREFILTER) 0x%x",dwRSVal)); switch(dwRSVal) { case D3DFILTER_NEAREST: case D3DFILTER_MIPNEAREST: pContext->bMinFilter = FALSE; break; case D3DFILTER_MIPLINEAR: case D3DFILTER_LINEAR: case D3DFILTER_LINEARMIPNEAREST: case D3DFILTER_LINEARMIPLINEAR: pContext->bMinFilter = TRUE; break; default: break; } DIRTY_TEXTURE; break; case D3DRENDERSTATE_SRCBLEND: DBG_D3D((8, "ChangeState: Source Blend (D3DBLEND):")); DECODEBLEND(4, dwRSVal); switch (dwRSVal) { case D3DBLEND_ZERO: pSoftPermedia->AlphaBlendMode.SourceBlend = __PERMEDIA_BLEND_FUNC_ZERO; break; case D3DBLEND_ONE: pSoftPermedia->AlphaBlendMode.SourceBlend = __PERMEDIA_BLEND_FUNC_ONE; break; case D3DBLEND_SRCALPHA: pSoftPermedia->AlphaBlendMode.SourceBlend = __PERMEDIA_BLEND_FUNC_SRC_ALPHA; break; default: DBG_D3D((2,"Invalid Source Blend! - %d", dwRSVal)); break; } // If alpha is on, we may need to validate the chosen blend if (*pFlags & CTXT_HAS_ALPHABLEND_ENABLED) DIRTY_ALPHABLEND; break; case D3DRENDERSTATE_DESTBLEND: DBG_D3D((8, "ChangeState: Destination Blend (D3DBLEND):")); DECODEBLEND(4, dwRSVal); switch (dwRSVal) { case D3DBLEND_ZERO: pSoftPermedia->AlphaBlendMode.DestinationBlend = __PERMEDIA_BLEND_FUNC_ZERO; break; case D3DBLEND_ONE: pSoftPermedia->AlphaBlendMode.DestinationBlend = __PERMEDIA_BLEND_FUNC_ONE; break; case D3DBLEND_INVSRCALPHA: pSoftPermedia->AlphaBlendMode.DestinationBlend = __PERMEDIA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA; break; default: DBG_D3D((2,"Invalid Dest Blend! - %d", dwRSVal)); break; } // If alpha is on, we may need to validate the chosen blend if (*pFlags & CTXT_HAS_ALPHABLEND_ENABLED) DIRTY_ALPHABLEND; break; case D3DRENDERSTATE_CULLMODE: DBG_D3D((8, "ChangeState: Cull Mode " "(D3DCULL) 0x%x",dwRSVal)); pContext->CullMode = (D3DCULL) dwRSVal; switch(dwRSVal) { case D3DCULL_NONE: #ifdef P2_CHIP_CULLING pSoftPermedia->DeltaMode.BackfaceCull = 0; #endif break; case D3DCULL_CCW: #ifdef P2_CHIP_CULLING RENDER_NEGATIVE_CULL(pContext->RenderCommand); pSoftPermedia->DeltaMode.BackfaceCull = 1; #endif break; case D3DCULL_CW: #ifdef P2_CHIP_CULLING RENDER_POSITIVE_CULL(pContext->RenderCommand); pSoftPermedia->DeltaMode.BackfaceCull = 1; #endif break; } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); COMMITDMAPTR(); break; case D3DRENDERSTATE_ZFUNC: DBG_D3D((8, "ChangeState: Z Compare function " "(D3DCMPFUNC) 0x%x",dwRSVal)); switch (dwRSVal) { case D3DCMP_NEVER: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_NEVER; break; case D3DCMP_LESS: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_LESS; break; case D3DCMP_EQUAL: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_EQUAL; break; case D3DCMP_LESSEQUAL: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_LESS_OR_EQUAL; break; case D3DCMP_GREATER: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_GREATER; break; case D3DCMP_NOTEQUAL: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_NOT_EQUAL; break; case D3DCMP_GREATEREQUAL: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_GREATER_OR_EQUAL; break; case D3DCMP_ALWAYS: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_ALWAYS; break; default: pSoftPermedia->DepthMode.CompareMode = __PERMEDIA_DEPTH_COMPARE_MODE_LESS_OR_EQUAL; break; } DIRTY_ZBUFFER; break; case D3DRENDERSTATE_ALPHAREF: DBG_D3D((8, "ChangeState: Alpha Reference " "(D3DFIXED) 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_ALPHAFUNC: DBG_D3D((8, "ChangeState: Alpha compare function " "(D3DCMPFUNC) 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_DITHERENABLE: DBG_D3D((8, "ChangeState: Dither Enable " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal != 0) { pSoftPermedia->DitherMode.DitherEnable = DITHER_ENABLE; } else { pSoftPermedia->DitherMode.DitherEnable = 0; } RESERVEDMAPTR(1); COPY_PERMEDIA_DATA(DitherMode, pSoftPermedia->DitherMode); COMMITDMAPTR(); break; case D3DRENDERSTATE_COLORKEYENABLE: DBG_D3D((8, "ChangeState: ColorKey Enable " "(BOOL) 0x%x",dwRSVal)); DIRTY_TEXTURE; break; case D3DRENDERSTATE_MIPMAPLODBIAS: DBG_D3D((8, "ChangeState: Mipmap LOD Bias " "(INT) 0x%x", dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_ALPHABLENDENABLE: DBG_D3D((8, "ChangeState: Blend Enable " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal != 0) { if (!(*pFlags & CTXT_HAS_ALPHABLEND_ENABLED)) { // Set the blend enable flag in the render context struct *pFlags |= CTXT_HAS_ALPHABLEND_ENABLED; DIRTY_ALPHABLEND; } } else { if (*pFlags & CTXT_HAS_ALPHABLEND_ENABLED) { // Turn off blend enable flag in render context struct *pFlags &= ~CTXT_HAS_ALPHABLEND_ENABLED; DIRTY_ALPHABLEND; } } break; case D3DRENDERSTATE_FOGENABLE: DBG_D3D((8, "ChangeState: Fog Enable " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal != 0) { *pFlags |= CTXT_HAS_FOGGING_ENABLED; RENDER_FOG_ENABLE(pContext->RenderCommand); } else { *pFlags &= ~CTXT_HAS_FOGGING_ENABLED; RENDER_FOG_DISABLE(pContext->RenderCommand); } DIRTY_TEXTURE; break; case D3DRENDERSTATE_FOGCOLOR: DBG_D3D((8, "ChangeState: Fog Color " "(D3DCOLOR) 0x%x",dwRSVal)); { BYTE red, green, blue, alpha; red = (BYTE)RGBA_GETRED(dwRSVal); green = (BYTE)RGBA_GETGREEN(dwRSVal); blue = (BYTE)RGBA_GETBLUE(dwRSVal); alpha = (BYTE)RGBA_GETALPHA(dwRSVal); DBG_D3D((4,"FogColor: Red 0x%x, Green 0x%x, Blue 0x%x", red, green, blue)); RESERVEDMAPTR(1); pSoftPermedia->FogColor = RGBA_MAKE(blue, green, red, alpha); SEND_PERMEDIA_DATA(FogColor, pSoftPermedia->FogColor); COMMITDMAPTR(); } break; case D3DRENDERSTATE_SPECULARENABLE: DBG_D3D((8, "ChangeState: Specular Lighting " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal) { *pFlags |= CTXT_HAS_SPECULAR_ENABLED; } else { *pFlags &= ~CTXT_HAS_SPECULAR_ENABLED; } break; case D3DRENDERSTATE_FILLMODE: DBG_D3D((8, "ChangeState: Fill Mode 0x%x",dwRSVal)); pContext->Hdr.FillMode = dwRSVal; RESERVEDMAPTR(1); switch (dwRSVal) { case D3DFILL_POINT: DBG_D3D((4, "RM = Point")); // Restore the RasterizerMode SEND_PERMEDIA_DATA(RasterizerMode, 0); break; case D3DFILL_WIREFRAME: DBG_D3D((4, "RM = Wire")); // Add nearly a half in the delta case for lines // (lines aren't biased on a delta). SEND_PERMEDIA_DATA(RasterizerMode, BIAS_NEARLY_HALF); break; case D3DFILL_SOLID: DBG_D3D((4, "RM = Solid")); // Restore the RasterizerMode SEND_PERMEDIA_DATA(RasterizerMode, 0); break; default: // Illegal value DBG_D3D((4, "RM = Nonsense")); pContext->Hdr.FillMode = D3DFILL_SOLID; // Restore the RasterizerMode SEND_PERMEDIA_DATA(RasterizerMode, 0); break; } COMMITDMAPTR(); break; case D3DRENDERSTATE_TEXTUREPERSPECTIVE: DBG_D3D((8, "ChangeState: Texture Perspective " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal != 0) { pSoftPermedia->TextureAddressMode.PerspectiveCorrection = 1; pSoftPermedia->DeltaMode.TextureParameterMode = 2; // Normalise *pFlags |= CTXT_HAS_PERSPECTIVE_ENABLED; } else { pSoftPermedia->TextureAddressMode.PerspectiveCorrection = 0; pSoftPermedia->DeltaMode.TextureParameterMode = 1; // Clamp *pFlags &= ~CTXT_HAS_PERSPECTIVE_ENABLED; } RESERVEDMAPTR(3); // Just to ensure that the texture unit // can take the perspective change COPY_PERMEDIA_DATA(LBWriteMode, pSoftPermedia->LBWriteMode); COPY_PERMEDIA_DATA(TextureAddressMode, pSoftPermedia->TextureAddressMode); COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); COMMITDMAPTR(); break; case D3DRENDERSTATE_ZENABLE: DBG_D3D((8, "ChangeState: Z Enable " "(TRUE) 0x%x",dwRSVal)); if (dwRSVal != 0) { if ( (!(*pFlags & CTXT_HAS_ZBUFFER_ENABLED)) && (pContext->ZBufferHandle) ) { // Local Buffer Write mode DBG_D3D((4, " Enabling Z Buffer")); *pFlags |= CTXT_HAS_ZBUFFER_ENABLED; DIRTY_ZBUFFER; } } else { if (*pFlags & CTXT_HAS_ZBUFFER_ENABLED) { DBG_D3D((4, " Disabling Z Buffer")); *pFlags &= ~CTXT_HAS_ZBUFFER_ENABLED; DIRTY_ZBUFFER; } } break; case D3DRENDERSTATE_SHADEMODE: DBG_D3D((8, "ChangeState: Shade mode " "(D3DSHADEMODE) 0x%x",dwRSVal)); RESERVEDMAPTR(2); switch(dwRSVal) { case D3DSHADE_PHONG: case D3DSHADE_GOURAUD: if (!(*pFlags & CTXT_HAS_GOURAUD_ENABLED)) { pSoftPermedia->ColorDDAMode.ShadeMode = 1; // Set DDA to gouraud COPY_PERMEDIA_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode); pSoftPermedia->DeltaMode.SmoothShadingEnable = 1; COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); *pFlags |= CTXT_HAS_GOURAUD_ENABLED; // If we are textureing, some changes may need to be made if (pContext->CurrentTextureHandle != 0) DIRTY_TEXTURE; } break; case D3DSHADE_FLAT: if (*pFlags & CTXT_HAS_GOURAUD_ENABLED) { pSoftPermedia->ColorDDAMode.ShadeMode = 0; // Set DDA to flat COPY_PERMEDIA_DATA(ColorDDAMode, pSoftPermedia->ColorDDAMode); pSoftPermedia->DeltaMode.SmoothShadingEnable = 0; COPY_PERMEDIA_DATA(DeltaMode, pSoftPermedia->DeltaMode); *pFlags &= ~CTXT_HAS_GOURAUD_ENABLED; // If we are textureing, some changes may need to be made if (pContext->CurrentTextureHandle != 0) DIRTY_TEXTURE; } break; } COMMITDMAPTR(); break; case D3DRENDERSTATE_ROP2: DBG_D3D((8, "ChangeState: ROP (D3DROP2) 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_ZVISIBLE: // From DX6 onwards this is an obsolete render state. // The D3D runtime does not support it anymore so drivers // don't need to implement it DBG_D3D((8, "ChangeState: Z Visible 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_PLANEMASK: DBG_D3D((8, "ChangeState: Plane Mask " "(ULONG) 0x%x",dwRSVal)); RESERVEDMAPTR(1); SEND_PERMEDIA_DATA(FBHardwareWriteMask, (DWORD)dwRSVal); COMMITDMAPTR(); break; case D3DRENDERSTATE_MONOENABLE: DBG_D3D((8, "ChangeState: Mono Raster enable " "(BOOL) 0x%x", dwRSVal)); if (dwRSVal) { *pFlags |= CTXT_HAS_MONO_ENABLED; } else { *pFlags &= ~CTXT_HAS_MONO_ENABLED; } break; case D3DRENDERSTATE_SUBPIXEL: DBG_D3D((8, "ChangeState: SubPixel Correction " "(BOOL) 0x%x", dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_SUBPIXELX: DBG_D3D((8, "ChangeState: SubPixel Correction (xOnly) " "(BOOL) 0x%x", dwRSVal)); NOT_HANDLED; break; #if D3D_STENCIL // // Stenciling Render States // case D3DRENDERSTATE_STENCILENABLE: DBG_D3D((8, "ChangeState: Stencil Enable " "(ULONG) 0x%x",dwRSVal)); if (dwRSVal != 0) { pSoftPermedia->StencilMode.UnitEnable = __PERMEDIA_ENABLE; } else { pSoftPermedia->StencilMode.UnitEnable = __PERMEDIA_DISABLE; } DIRTY_ZBUFFER; break; case D3DRENDERSTATE_STENCILFAIL: DBG_D3D((8, "ChangeState: Stencil Fail Method " "(ULONG) 0x%x",dwRSVal)); switch (dwRSVal) { case D3DSTENCILOP_KEEP: pSoftPermedia->StencilMode.SFail = __PERMEDIA_STENCIL_METHOD_KEEP; break; case D3DSTENCILOP_ZERO: pSoftPermedia->StencilMode.SFail = __PERMEDIA_STENCIL_METHOD_ZERO; break; case D3DSTENCILOP_REPLACE: pSoftPermedia->StencilMode.SFail = __PERMEDIA_STENCIL_METHOD_REPLACE; break; case D3DSTENCILOP_INCRSAT: case D3DSTENCILOP_INCR: pSoftPermedia->StencilMode.SFail = __PERMEDIA_STENCIL_METHOD_INCR; break; case D3DSTENCILOP_DECR: case D3DSTENCILOP_DECRSAT: pSoftPermedia->StencilMode.SFail = __PERMEDIA_STENCIL_METHOD_DECR; break; case D3DSTENCILOP_INVERT: pSoftPermedia->StencilMode.SFail = __PERMEDIA_STENCIL_METHOD_INVERT; break; default: DBG_D3D((2, " Unrecognized stencil method 0x%x", dwRSVal)); } DIRTY_ZBUFFER; break; case D3DRENDERSTATE_STENCILZFAIL: DBG_D3D((8, "ChangeState: Stencil Pass Depth Fail Method " "(ULONG) 0x%x",dwRSVal)); switch (dwRSVal) { case D3DSTENCILOP_KEEP: pSoftPermedia->StencilMode.DPFail = __PERMEDIA_STENCIL_METHOD_KEEP; break; case D3DSTENCILOP_ZERO: pSoftPermedia->StencilMode.DPFail = __PERMEDIA_STENCIL_METHOD_ZERO; break; case D3DSTENCILOP_REPLACE: pSoftPermedia->StencilMode.DPFail = __PERMEDIA_STENCIL_METHOD_REPLACE; break; case D3DSTENCILOP_INCRSAT: case D3DSTENCILOP_INCR: pSoftPermedia->StencilMode.DPFail = __PERMEDIA_STENCIL_METHOD_INCR; break; case D3DSTENCILOP_DECR: case D3DSTENCILOP_DECRSAT: pSoftPermedia->StencilMode.DPFail = __PERMEDIA_STENCIL_METHOD_DECR; break; case D3DSTENCILOP_INVERT: pSoftPermedia->StencilMode.DPFail = __PERMEDIA_STENCIL_METHOD_INVERT; break; default: DBG_D3D((2, " Unrecognized stencil method 0x%x", dwRSVal)); } DIRTY_ZBUFFER; break; case D3DRENDERSTATE_STENCILPASS: DBG_D3D((8, "ChangeState: Stencil Pass Method " "(ULONG) 0x%x",dwRSVal)); switch (dwRSVal) { case D3DSTENCILOP_KEEP: pSoftPermedia->StencilMode.DPPass = __PERMEDIA_STENCIL_METHOD_KEEP; break; case D3DSTENCILOP_ZERO: pSoftPermedia->StencilMode.DPPass = __PERMEDIA_STENCIL_METHOD_ZERO; break; case D3DSTENCILOP_REPLACE: pSoftPermedia->StencilMode.DPPass = __PERMEDIA_STENCIL_METHOD_REPLACE; break; case D3DSTENCILOP_INCRSAT: case D3DSTENCILOP_INCR: pSoftPermedia->StencilMode.DPPass = __PERMEDIA_STENCIL_METHOD_INCR; break; case D3DSTENCILOP_DECR: case D3DSTENCILOP_DECRSAT: pSoftPermedia->StencilMode.DPPass = __PERMEDIA_STENCIL_METHOD_DECR; break; case D3DSTENCILOP_INVERT: pSoftPermedia->StencilMode.DPPass = __PERMEDIA_STENCIL_METHOD_INVERT; break; default: DBG_D3D((2, " Unrecognized stencil method 0x%x", dwRSVal)); } DIRTY_ZBUFFER; break; case D3DRENDERSTATE_STENCILFUNC: DBG_D3D((8, "ChangeState: Stencil Comparison Function " "(ULONG) 0x%x",dwRSVal)); switch (dwRSVal) { case D3DCMP_NEVER: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_NEVER; break; case D3DCMP_LESS: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_LESS; break; case D3DCMP_EQUAL: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_EQUAL; break; case D3DCMP_LESSEQUAL: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_LESS_OR_EQUAL; break; case D3DCMP_GREATER: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_GREATER; break; case D3DCMP_NOTEQUAL: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_NOT_EQUAL; break; case D3DCMP_GREATEREQUAL: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_GREATER_OR_EQUAL; break; case D3DCMP_ALWAYS: pSoftPermedia->StencilMode.CompareFunction = __PERMEDIA_STENCIL_COMPARE_MODE_ALWAYS; break; default: DBG_D3D((2, " Unrecognized stencil comparison function 0x%x", dwRSVal)); } DIRTY_ZBUFFER; break; case D3DRENDERSTATE_STENCILREF: DBG_D3D((8, "ChangeState: Stencil Reference Value " "(ULONG) 0x%x",dwRSVal)); pSoftPermedia->StencilData.ReferenceValue = ( dwRSVal & 0x0001 ); DIRTY_ZBUFFER; break; case D3DRENDERSTATE_STENCILMASK: DBG_D3D((8, "ChangeState: Stencil Compare Mask " "(ULONG) 0x%x",dwRSVal)); pSoftPermedia->StencilData.CompareMask = ( dwRSVal & 0x0001 ); DIRTY_ZBUFFER; break; case D3DRENDERSTATE_STENCILWRITEMASK: DBG_D3D((8, "ChangeState: Stencil Write Mask " "(ULONG) 0x%x",dwRSVal)); pSoftPermedia->StencilData.WriteMask = ( dwRSVal & 0x0001 ); DIRTY_ZBUFFER; break; #endif // D3D_STENCIL // // Stippling // case D3DRENDERSTATE_STIPPLEDALPHA: DBG_D3D((8, "ChangeState: Stippled Alpha " "(BOOL) 0x%x",dwRSVal)); if (dwRSVal) { if (!(*pFlags & CTXT_HAS_ALPHASTIPPLE_ENABLED)) { // Force a new start on the Alpha pattern pContext->LastAlpha = 16; *pFlags |= CTXT_HAS_ALPHASTIPPLE_ENABLED; if (pContext->bKeptStipple == TRUE) { RENDER_AREA_STIPPLE_DISABLE(pContext->RenderCommand); } } } else { if (*pFlags & CTXT_HAS_ALPHASTIPPLE_ENABLED) { // If Alpha Stipple is being turned off, turn the normal // stipple back on, and enable it. int i; RESERVEDMAPTR(8); for (i = 0; i < 8; i++) { SEND_PERMEDIA_DATA_OFFSET(AreaStipplePattern0, (DWORD)pContext->CurrentStipple[i], i); } COMMITDMAPTR(); *pFlags &= ~CTXT_HAS_ALPHASTIPPLE_ENABLED; if (pContext->bKeptStipple == TRUE) { RENDER_AREA_STIPPLE_ENABLE(pContext->RenderCommand); } } } break; case D3DRENDERSTATE_STIPPLEENABLE: DBG_D3D((8, "ChangeState: Stipple Enable " "(BOOL) 0x%x", dwRSVal)); if (dwRSVal) { if (!(*pFlags & CTXT_HAS_ALPHASTIPPLE_ENABLED)) { RENDER_AREA_STIPPLE_ENABLE(pContext->RenderCommand); } pContext->bKeptStipple = TRUE; } else { RENDER_AREA_STIPPLE_DISABLE(pContext->RenderCommand); pContext->bKeptStipple = FALSE; } break; case D3DRENDERSTATE_CLIPPING: DBG_D3D((8, "ChangeState: Clipping 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_LIGHTING: DBG_D3D((8, "ChangeState: Lighting 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_EXTENTS: DBG_D3D((8, "ChangeState: Extents 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_AMBIENT: DBG_D3D((8, "ChangeState: Ambient 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_FOGVERTEXMODE: DBG_D3D((8, "ChangeState: Fog Vertex Mode 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_COLORVERTEX: DBG_D3D((8, "ChangeState: Color Vertex 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_LOCALVIEWER: DBG_D3D((8, "ChangeState: LocalViewer 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_NORMALIZENORMALS: DBG_D3D((8, "ChangeState: Normalize Normals 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_COLORKEYBLENDENABLE: DBG_D3D((8, "ChangeState: Colorkey Blend Enable 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE: DBG_D3D((8, "ChangeState: Diffuse Material Source 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_SPECULARMATERIALSOURCE: DBG_D3D((8, "ChangeState: Specular Material Source 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_AMBIENTMATERIALSOURCE: DBG_D3D((8, "ChangeState: Ambient Material Source 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE: DBG_D3D((8, "ChangeState: Emmisive Material Source 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_VERTEXBLEND: DBG_D3D((8, "ChangeState: Vertex Blend 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_CLIPPLANEENABLE: DBG_D3D((8, "ChangeState: Clip Plane Enable 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_SCENECAPTURE: // This state pass TRUE or FALSE to replace the functionality // of D3DHALCallbacks->SceneCapture(), Permedia2 Hardware doesn't // need begin/end scene information, therefore it's a NOOP here. if (dwRSVal) TextureCacheManagerResetStatCounters(pContext->pTextureManager); DBG_D3D((8,"D3DRENDERSTATE_SCENECAPTURE=%x", (DWORD)dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_EVICTMANAGEDTEXTURES: DBG_D3D((8,"D3DRENDERSTATE_EVICTMANAGEDTEXTURES=%x", (DWORD)dwRSVal)); if (NULL != pContext->pTextureManager) TextureCacheManagerEvictTextures(pContext->pTextureManager); break; //@@BEGIN_DDKSPLIT #if D3D_POINTSPRITES case D3DRENDERSTATE_POINTSIZE: DBG_D3D((8, "ChangeState: Point size 0x%x",dwRSVal)); (DWORD&)(pContext->fPointSize) = dwRSVal; break; case D3DRENDERSTATE_POINTSPRITE_ENABLE: DBG_D3D((8, "ChangeState: Point Sprite Enable 0x%x",dwRSVal)); pContext->bPointSpriteEnabled = dwRSVal; break; // All of the following point sprite related render states are // ignored by this driver since we are a Non-TnLHal driver. case D3DRENDERSTATE_POINTATTENUATION_A: DBG_D3D((8, "ChangeState: Point Attenuation A 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_POINTATTENUATION_B: DBG_D3D((8, "ChangeState: Point Attenuation B 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_POINTATTENUATION_C: DBG_D3D((8, "ChangeState: Point Attenuation C 0x%x",dwRSVal)); NOT_HANDLED; break; case D3DRENDERSTATE_POINTSIZEMIN: DBG_D3D((8, "ChangeState: Point Size Min 0x%x",dwRSVal)); NOT_HANDLED; break; #endif // D3D_POINTSPRITES //@@END_DDKSPLIT case D3DRENDERSTATE_WRAP0: case D3DRENDERSTATE_WRAP1: case D3DRENDERSTATE_WRAP2: case D3DRENDERSTATE_WRAP3: case D3DRENDERSTATE_WRAP4: case D3DRENDERSTATE_WRAP5: case D3DRENDERSTATE_WRAP6: case D3DRENDERSTATE_WRAP7: DBG_D3D((8, "ChangeState: Wrap(%x) " "(BOOL) 0x%x",(dwRSType - D3DRENDERSTATE_WRAPBIAS ),dwRSVal)); pContext->dwWrap[dwRSType - D3DRENDERSTATE_WRAPBIAS] = dwRSVal; break; default: if ((dwRSType >= D3DRENDERSTATE_STIPPLEPATTERN00) && (dwRSType <= D3DRENDERSTATE_STIPPLEPATTERN07)) { DBG_D3D((8, "ChangeState: Loading Stipple0x%x with 0x%x", dwRSType - D3DRENDERSTATE_STIPPLEPATTERN00, (DWORD)dwRSVal)); pContext->CurrentStipple[(dwRSType - D3DRENDERSTATE_STIPPLEPATTERN00)] = (BYTE)dwRSVal; if (!(*pFlags & CTXT_HAS_ALPHASTIPPLE_ENABLED)) { // Flat-Stippled Alpha is not on, so use the // current stipple pattern RESERVEDMAPTR(1); SEND_PERMEDIA_DATA_OFFSET(AreaStipplePattern0, (DWORD)dwRSVal, dwRSType - D3DRENDERSTATE_STIPPLEPATTERN00); COMMITDMAPTR(); } } else { DBG_D3D((2, "ChangeState: Unhandled opcode = %d", dwRSType)); } break; } // switch (dwRSType of renderstate) // Mirror any change that happened in the render states into TSS 0 __MapRS_Into_TSS0(pContext, dwRSType, dwRSVal); DBG_D3D((10,"Exiting __ProcessRenderStates")); } //----------------------------------------------------------------------------- // // DWORD __ProcessPermediaStates // // Handle render state changes that arrive through the D3DDP2OP_RENDERSTATE // token in the DP2 command stream. // //----------------------------------------------------------------------------- DWORD __ProcessPermediaStates(PERMEDIA_D3DCONTEXT* pContext, DWORD dwCount, LPD3DSTATE lpState, LPDWORD lpStateMirror) { DWORD dwRSType, dwRSVal, i; DBG_D3D((10,"Entering __ProcessPermediaStates")); DBG_D3D((4, "__ProcessPermediaStates: Processing %d State changes", dwCount)); // Loop through all renderstates passed in the DP2 command stream for (i = 0; i < dwCount; i++, lpState++) { dwRSType = (DWORD) lpState->drstRenderStateType; dwRSVal = (DWORD) lpState->dwArg[0]; DBG_D3D((8, "__ProcessPermediaStates state %d value = %d", dwRSType, dwRSVal)); // Check validity of the render state if (!VALID_STATE(dwRSType)) { DBG_D3D((0, "state 0x%08x is invalid", dwRSType)); return DDERR_INVALIDPARAMS; } // Verify if state needs to be overrided or ignored if (IS_OVERRIDE(dwRSType)) { DWORD override = GET_OVERRIDE(dwRSType); if (dwRSVal) { DBG_D3D((4, "in RenderState, setting override for state %d", override)); STATESET_SET(pContext->overrides, override); } else { DBG_D3D((4, "in RenderState, clearing override for state %d", override)); STATESET_CLEAR(pContext->overrides, override); } continue; } if (STATESET_ISSET(pContext->overrides, dwRSType)) { DBG_D3D((4, "in RenderState, state %d is overridden, ignoring", dwRSType)); continue; } #if D3D_STATEBLOCKS if (!pContext->bStateRecMode) { #endif D3D_STATEBLOCKS // Store the state in the context pContext->RenderStates[dwRSType] = dwRSVal; // Mirror value if ( lpStateMirror ) lpStateMirror[dwRSType] = dwRSVal; __ProcessRenderStates(pContext, dwRSType, dwRSVal); #if D3D_STATEBLOCKS } else { if (pContext->pCurrSS != NULL) { DBG_D3D((6,"Recording RS %x = %x",dwRSType,dwRSVal)); // Recording the state in a stateblock pContext->pCurrSS->u.uc.RenderStates[dwRSType] = dwRSVal; FLAG_SET(pContext->pCurrSS->u.uc.bStoredRS,dwRSType); } } #endif D3D_STATEBLOCKS } // for (i) DBG_D3D((10,"Exiting __ProcessPermediaStates")); return DD_OK; } // __ProcessPermediaStates #if D3D_STATEBLOCKS //----------------------------------------------------------------------------- // // P2StateSetRec *FindStateSet // // Find a state identified by dwHandle starting from pRootSS. // If not found, returns NULL. // //----------------------------------------------------------------------------- P2StateSetRec *FindStateSet(PERMEDIA_D3DCONTEXT* pContext, DWORD dwHandle) { if (dwHandle <= pContext->dwMaxSSIndex) return pContext->pIndexTableSS[dwHandle - 1]; else { DBG_D3D((2,"State set %x not found (Max = %x)", dwHandle, pContext->dwMaxSSIndex)); return NULL; } } //----------------------------------------------------------------------------- // // void DumpStateSet // // Dump info stored in a state set // //----------------------------------------------------------------------------- #define ELEMS_IN_ARRAY(a) ((sizeof(a)/sizeof(a[0]))) void DumpStateSet(P2StateSetRec *pSSRec) { DWORD i; DBG_D3D((0,"DumpStateSet %x, Id=%x bCompressed=%x", pSSRec,pSSRec->dwHandle,pSSRec->bCompressed)); if (!pSSRec->bCompressed) { // uncompressed state set // Dump render states values for (i=0; i< MAX_STATE; i++) { DBG_D3D((0,"RS %x = %x",i, pSSRec->u.uc.RenderStates[i])); } // Dump TSS's values for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++) { DBG_D3D((0,"TSS %x = %x",i, pSSRec->u.uc.TssStates[i])); } // Dump RS bit masks for (i=0; i< ELEMS_IN_ARRAY(pSSRec->u.uc.bStoredRS); i++) { DBG_D3D((0,"bStoredRS[%x] = %x",i, pSSRec->u.uc.bStoredRS[i])); } // Dump TSS bit masks for (i=0; i< ELEMS_IN_ARRAY(pSSRec->u.uc.bStoredTSS); i++) { DBG_D3D((0,"bStoredTSS[%x] = %x",i, pSSRec->u.uc.bStoredTSS[i])); } } else { // compressed state set DBG_D3D((0,"dwNumRS =%x dwNumTSS=%x", pSSRec->u.cc.dwNumRS,pSSRec->u.cc.dwNumTSS)); // dump compressed state for (i=0; i< pSSRec->u.cc.dwNumTSS + pSSRec->u.cc.dwNumRS; i++) { DBG_D3D((0,"RS/TSS %x = %x", pSSRec->u.cc.pair[i].dwType, pSSRec->u.cc.pair[i].dwValue)); } } } //----------------------------------------------------------------------------- // // void AddStateSetIndexTableEntry // // Add an antry to the index table. If necessary, grow it. //----------------------------------------------------------------------------- void AddStateSetIndexTableEntry(PERMEDIA_D3DCONTEXT* pContext, DWORD dwNewHandle, P2StateSetRec *pNewSSRec) { DWORD dwNewSize; P2StateSetRec **pNewIndexTableSS; // If the current list is not large enough, we'll have to grow a new one. if (dwNewHandle > pContext->dwMaxSSIndex) { // New size of our index table // (round up dwNewHandle in steps of SSPTRS_PERPAGE) dwNewSize = ((dwNewHandle -1 + SSPTRS_PERPAGE) / SSPTRS_PERPAGE) * SSPTRS_PERPAGE; // we have to grow our list pNewIndexTableSS = (P2StateSetRec **) ENGALLOCMEM( FL_ZERO_MEMORY, dwNewSize*sizeof(P2StateSetRec *), ALLOC_TAG); if (!pNewIndexTableSS) { // we weren't able to grow the list so we will keep the old one // and (sigh) forget about this state set since that is the // safest thing to do. We will delete also the state set structure // since no one will otherwise be able to find it later. DBG_D3D((0,"Out of mem growing state set list," " droping current state set")); ENGFREEMEM(pNewSSRec); return; } if (pContext->pIndexTableSS) { // if we already had a previous list, we must transfer its data memcpy(pNewIndexTableSS, pContext->pIndexTableSS, pContext->dwMaxSSIndex*sizeof(P2StateSetRec *)); //and get rid of it ENGFREEMEM(pContext->pIndexTableSS); } // New index table data pContext->pIndexTableSS = pNewIndexTableSS; pContext->dwMaxSSIndex = dwNewSize; } // Store our state set pointer into our access list pContext->pIndexTableSS[dwNewHandle - 1] = pNewSSRec; } //----------------------------------------------------------------------------- // // void CompressStateSet // // Compress a state set so it uses the minimum necessary space. Since we expect // some apps to make extensive use of state sets we want to keep things tidy. // Returns address of new structure (ir old, if it wasn't compressed) // //----------------------------------------------------------------------------- P2StateSetRec * CompressStateSet(PERMEDIA_D3DCONTEXT* pContext, P2StateSetRec *pUncompressedSS) { P2StateSetRec *pCompressedSS; DWORD i, dwSize, dwIndex, dwCount; // Create a new state set of just the right size we need // Calculate how large dwCount = 0; for (i=0; i< MAX_STATE; i++) if (IS_FLAG_SET(pUncompressedSS->u.uc.bStoredRS , i)) { dwCount++; }; for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++) if (IS_FLAG_SET(pUncompressedSS->u.uc.bStoredTSS , i)) { dwCount++; }; // Create a new state set of just the right size we need // ANY CHANGE MADE TO THE P2StateSetRec structure MUST BE REFLECTED HERE! dwSize = 2*sizeof(DWORD) + // handle , flags 2*sizeof(DWORD) + // # of RS & TSS 2*dwCount*sizeof(DWORD); // compressed structure if (dwSize >= sizeof(P2StateSetRec)) { // it is not efficient to compress, leave uncompressed ! pUncompressedSS->bCompressed = FALSE; return pUncompressedSS; } pCompressedSS = (P2StateSetRec *)ENGALLOCMEM( FL_ZERO_MEMORY, dwSize, ALLOC_TAG); if (pCompressedSS) { // adjust data in new compressed state set pCompressedSS->bCompressed = TRUE; pCompressedSS->dwHandle = pUncompressedSS->dwHandle; // Transfer our info to this new state set pCompressedSS->u.cc.dwNumRS = 0; pCompressedSS->u.cc.dwNumTSS = 0; dwIndex = 0; for (i=0; i< MAX_STATE; i++) if (IS_FLAG_SET(pUncompressedSS->u.uc.bStoredRS , i)) { pCompressedSS->u.cc.pair[dwIndex].dwType = i; pCompressedSS->u.cc.pair[dwIndex].dwValue = pUncompressedSS->u.uc.RenderStates[i]; pCompressedSS->u.cc.dwNumRS++; dwIndex++; } for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++) if (IS_FLAG_SET(pUncompressedSS->u.uc.bStoredTSS , i)) { pCompressedSS->u.cc.pair[dwIndex].dwType = i; pCompressedSS->u.cc.pair[dwIndex].dwValue = pUncompressedSS->u.uc.TssStates[i]; pCompressedSS->u.cc.dwNumTSS++; dwIndex++; } // Get rid of the old(uncompressed) one ENGFREEMEM(pUncompressedSS); return pCompressedSS; } else { DBG_D3D((0,"Not enough memory left to compress D3D state set")); pUncompressedSS->bCompressed = FALSE; return pUncompressedSS; } } //----------------------------------------------------------------------------- // // void __DeleteAllStateSets // // Delete any remaining state sets for cleanup purpouses // //----------------------------------------------------------------------------- void __DeleteAllStateSets(PERMEDIA_D3DCONTEXT* pContext) { P2StateSetRec *pSSRec; DWORD dwSSIndex; DBG_D3D((10,"Entering __DeleteAllStateSets")); if (pContext->pIndexTableSS) { for(dwSSIndex = 0; dwSSIndex < pContext->dwMaxSSIndex; dwSSIndex++) { if (pSSRec = pContext->pIndexTableSS[dwSSIndex]) { ENGFREEMEM(pSSRec); } } // free fast index table ENGFREEMEM(pContext->pIndexTableSS); } DBG_D3D((10,"Exiting __DeleteAllStateSets")); } //----------------------------------------------------------------------------- // // void __BeginStateSet // // Create a new state set identified by dwParam and start recording states // //----------------------------------------------------------------------------- void __BeginStateSet(PERMEDIA_D3DCONTEXT* pContext, DWORD dwParam) { DBG_D3D((10,"Entering __BeginStateSet dwParam=%08lx",dwParam)); P2StateSetRec *pSSRec; // Create a new state set pSSRec = (P2StateSetRec *)ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(P2StateSetRec), ALLOC_TAG); if (!pSSRec) { DBG_D3D((0,"Run out of memory for additional state sets")); return; } // remember handle to current state set pSSRec->dwHandle = dwParam; pSSRec->bCompressed = FALSE; // Get pointer to current recording state set pContext->pCurrSS = pSSRec; // Start recording mode pContext->bStateRecMode = TRUE; DBG_D3D((10,"Exiting __BeginStateSet")); } //----------------------------------------------------------------------------- // // void __EndStateSet // // stop recording states - revert to executing them. // //----------------------------------------------------------------------------- void __EndStateSet(PERMEDIA_D3DCONTEXT* pContext) { DWORD dwHandle; P2StateSetRec *pNewSSRec; DBG_D3D((10,"Entering __EndStateSet")); if (pContext->pCurrSS) { dwHandle = pContext->pCurrSS->dwHandle; // compress the current state set // Note: after being compressed the uncompressed version is free'd. pNewSSRec = CompressStateSet(pContext, pContext->pCurrSS); AddStateSetIndexTableEntry(pContext, dwHandle, pNewSSRec); } // No state set being currently recorded pContext->pCurrSS = NULL; // End recording mode pContext->bStateRecMode = FALSE; DBG_D3D((10,"Exiting __EndStateSet")); } //----------------------------------------------------------------------------- // // void __DeleteStateSet // // Delete the recorder state ste identified by dwParam // //----------------------------------------------------------------------------- void __DeleteStateSet(PERMEDIA_D3DCONTEXT* pContext, DWORD dwParam) { DBG_D3D((10,"Entering __DeleteStateSet dwParam=%08lx",dwParam)); P2StateSetRec *pSSRec; DWORD i; if (pSSRec = FindStateSet(pContext, dwParam)) { // Clear index table entry pContext->pIndexTableSS[dwParam - 1] = NULL; // Now delete the actual state set structure ENGFREEMEM(pSSRec); } DBG_D3D((10,"Exiting __DeleteStateSet")); } //----------------------------------------------------------------------------- // // void __ExecuteStateSet // // //----------------------------------------------------------------------------- void __ExecuteStateSet(PERMEDIA_D3DCONTEXT* pContext, DWORD dwParam) { DBG_D3D((10,"Entering __ExecuteStateSet dwParam=%08lx",dwParam)); P2StateSetRec *pSSRec; DWORD i; if (pSSRec = FindStateSet(pContext, dwParam)) { if (!pSSRec->bCompressed) { // uncompressed state set // Execute any necessary render states for (i=0; i< MAX_STATE; i++) if (IS_FLAG_SET(pSSRec->u.uc.bStoredRS , i)) { DWORD dwRSType, dwRSVal; dwRSType = i; dwRSVal = pSSRec->u.uc.RenderStates[dwRSType]; // Store the state in the context pContext->RenderStates[dwRSType] = dwRSVal; DBG_D3D((6,"__ExecuteStateSet RS %x = %x", dwRSType, dwRSVal)); // Process it __ProcessRenderStates(pContext, dwRSType, dwRSVal); DIRTY_TEXTURE; DIRTY_ZBUFFER; DIRTY_ALPHABLEND; } // Execute any necessary TSS's for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++) if (IS_FLAG_SET(pSSRec->u.uc.bStoredTSS , i)) { DWORD dwTSState, dwValue; dwTSState = i; dwValue = pSSRec->u.uc.TssStates[dwTSState]; DBG_D3D((6,"__ExecuteStateSet TSS %x = %x", dwTSState, dwValue)); // Store value associated to this stage state pContext->TssStates[dwTSState] = dwValue; // Perform any necessary preprocessing of it __HWPreProcessTSS(pContext, 0, dwTSState, dwValue); DIRTY_TEXTURE; } // Execute any necessary state for lights, materials, transforms, // viewport info, z range and clip planes - here - } else { // compressed state set // Execute any necessary render states for (i=0; i< pSSRec->u.cc.dwNumRS; i++) { DWORD dwRSType, dwRSVal; dwRSType = pSSRec->u.cc.pair[i].dwType; dwRSVal = pSSRec->u.cc.pair[i].dwValue; // Store the state in the context pContext->RenderStates[dwRSType] = dwRSVal; DBG_D3D((6,"__ExecuteStateSet RS %x = %x", dwRSType, dwRSVal)); // Process it __ProcessRenderStates(pContext, dwRSType, dwRSVal); DIRTY_TEXTURE; DIRTY_ZBUFFER; DIRTY_ALPHABLEND; } // Execute any necessary TSS's for (; i< pSSRec->u.cc.dwNumTSS + pSSRec->u.cc.dwNumRS; i++) { DWORD dwTSState, dwValue; dwTSState = pSSRec->u.cc.pair[i].dwType; dwValue = pSSRec->u.cc.pair[i].dwValue; DBG_D3D((6,"__ExecuteStateSet TSS %x = %x", dwTSState, dwValue)); // Store value associated to this stage state pContext->TssStates[dwTSState] = dwValue; // Perform any necessary preprocessing of it __HWPreProcessTSS(pContext, 0, dwTSState, dwValue); DIRTY_TEXTURE; } // Execute any necessary state for lights, materials, transforms, // viewport info, z range and clip planes - here - } } DBG_D3D((10,"Exiting __ExecuteStateSet")); } //----------------------------------------------------------------------------- // // void __CaptureStateSet // // //----------------------------------------------------------------------------- void __CaptureStateSet(PERMEDIA_D3DCONTEXT* pContext, DWORD dwParam) { DBG_D3D((10,"Entering __CaptureStateSet dwParam=%08lx",dwParam)); P2StateSetRec *pSSRec; DWORD i; if (pSSRec = FindStateSet(pContext, dwParam)) { if (!pSSRec->bCompressed) { // uncompressed state set // Capture any necessary render states for (i=0; i< MAX_STATE; i++) if (IS_FLAG_SET(pSSRec->u.uc.bStoredRS , i)) { pSSRec->u.uc.RenderStates[i] = pContext->RenderStates[i]; } // Capture any necessary TSS's for (i=0; i<= D3DTSS_TEXTURETRANSFORMFLAGS; i++) if (IS_FLAG_SET(pSSRec->u.uc.bStoredTSS , i)) { pSSRec->u.uc.TssStates[i] = pContext->TssStates[i]; } // Capture any necessary state for lights, materials, transforms, // viewport info, z range and clip planes - here - } else { // compressed state set // Capture any necessary render states for (i=0; i< pSSRec->u.cc.dwNumRS; i++) { DWORD dwRSType; dwRSType = pSSRec->u.cc.pair[i].dwType; pSSRec->u.cc.pair[i].dwValue = pContext->RenderStates[dwRSType]; } // Capture any necessary TSS's for (; i< pSSRec->u.cc.dwNumTSS + pSSRec->u.cc.dwNumRS; i++) { DWORD dwTSState; dwTSState = pSSRec->u.cc.pair[i].dwType; pSSRec->u.cc.pair[i].dwValue = pContext->TssStates[dwTSState]; } // Capture any necessary state for lights, materials, transforms, // viewport info, z range and clip planes - here - } } DBG_D3D((10,"Exiting __CaptureStateSet")); } #endif //D3D_STATEBLOCKS