namespace RGB_RAST_LIB_NAMESPACE { // TODO: Clean-up inline D3DI_SPANTEX_FORMAT ConvPixelFormat( const DDPIXELFORMAT& DDPixFmt) { if((DDPixFmt.dwFlags& DDPF_ZBUFFER)!= 0) { switch(DDPixFmt.dwZBitMask) { case( 0x0000FFFF): return D3DI_SPTFMT_Z16S0; case( 0xFFFFFF00): return D3DI_SPTFMT_Z24S8; case( 0x0000FFFE): return D3DI_SPTFMT_Z15S1; case( 0xFFFFFFFF): return D3DI_SPTFMT_Z32S0; default: return D3DI_SPTFMT_NULL; } } else if((DDPixFmt.dwFlags& DDPF_BUMPDUDV)!= 0) { switch( DDPixFmt.dwBumpDvBitMask) { case( 0x0000ff00): switch( DDPixFmt.dwRGBBitCount) { case( 24): return D3DI_SPTFMT_U8V8L8; case( 16): return D3DI_SPTFMT_U8V8; default: return D3DI_SPTFMT_NULL; } break; case( 0x000003e0): return D3DI_SPTFMT_U5V5L6; default: return D3DI_SPTFMT_NULL; } } else if((DDPixFmt.dwFlags& DDPF_PALETTEINDEXED8)!= 0) return D3DI_SPTFMT_PALETTE8; else if((DDPixFmt.dwFlags& DDPF_PALETTEINDEXED4)!= 0) return D3DI_SPTFMT_PALETTE4; else if( DDPixFmt.dwFourCC== MAKEFOURCC('U', 'Y', 'V', 'Y')) return D3DI_SPTFMT_UYVY; else if( DDPixFmt.dwFourCC== MAKEFOURCC('Y', 'U', 'Y', '2')) return D3DI_SPTFMT_YUY2; else if( DDPixFmt.dwFourCC== MAKEFOURCC('D', 'X', 'T', '1')) return D3DI_SPTFMT_DXT1; else if( DDPixFmt.dwFourCC== MAKEFOURCC('D', 'X', 'T', '2')) return D3DI_SPTFMT_DXT2; else if( DDPixFmt.dwFourCC== MAKEFOURCC('D', 'X', 'T', '3')) return D3DI_SPTFMT_DXT3; else if( DDPixFmt.dwFourCC== MAKEFOURCC('D', 'X', 'T', '4')) return D3DI_SPTFMT_DXT4; else if( DDPixFmt.dwFourCC== MAKEFOURCC('D', 'X', 'T', '5')) return D3DI_SPTFMT_DXT5; else { UINT uFmt = DDPixFmt.dwGBitMask | DDPixFmt.dwRBitMask; if (DDPixFmt.dwFlags & DDPF_ALPHAPIXELS) { uFmt |= DDPixFmt.dwRGBAlphaBitMask; } switch (uFmt) { case 0x00ffff00: switch (DDPixFmt.dwRGBBitCount) { case 32: return D3DI_SPTFMT_B8G8R8X8; case 24: return D3DI_SPTFMT_B8G8R8; default: return D3DI_SPTFMT_NULL; } break; case 0xffffff00: return D3DI_SPTFMT_B8G8R8A8; case 0xffe0: if (DDPixFmt.dwFlags & DDPF_ALPHAPIXELS) return D3DI_SPTFMT_B5G5R5A1; else return D3DI_SPTFMT_B5G6R5; case 0x07fe0: return D3DI_SPTFMT_B5G5R5; case 0xff0: return D3DI_SPTFMT_B4G4R4; case 0xfff0: return D3DI_SPTFMT_B4G4R4A4; case 0xff: return D3DI_SPTFMT_L8; case 0xffff: return D3DI_SPTFMT_L8A8; case 0xfc: return D3DI_SPTFMT_B2G3R3; default: return D3DI_SPTFMT_NULL; } } return D3DI_SPTFMT_NULL; } // Records the stride and the member offsets of the current FVF vertex type // Used to pack a FVF vertex into one known by the rasterizer, such as // RAST_GENERIC_VERTEX typedef struct _FVFDATA { // 0 means no according field INT16 offsetRHW; INT16 offsetPSize; INT16 offsetDiff; INT16 offsetSpec; INT16 offsetTex[D3DHAL_TSS_MAXSTAGES]; UINT16 stride; RAST_VERTEX_TYPE vtxType; DWORD preFVF; INT TexIdx[D3DHAL_TSS_MAXSTAGES]; UINT cActTex; }FVFDATA; class CRGBStateSet: public CSubStateSet< CRGBStateSet, CRGBContext> { public: CRGBStateSet( CRGBContext& C, const D3DHAL_DP2COMMAND* pBeginSS, const D3DHAL_DP2COMMAND* pEndSS): CSubStateSet< CRGBStateSet, CRGBContext>( C, pBeginSS, pEndSS) { } ~CRGBStateSet() { } }; typedef CStdDrawPrimitives2< CRGBContext, CRGBStateSet, static_hash_map< DWORD, CRGBStateSet, 32> > TDrawPrimitives2; typedef CSubContext< CRGBContext, CRGBDriver::TPerDDrawData, CRTarget< CRGBDriver::TSurface*, CRGBDriver::TPerDDrawData::TSurfDBEntry*> > TSubContext; class CRGBContext: public TSubContext, public TDrawPrimitives2, public CStdDP2SetVertexShaderStore< CRGBContext>, public CStdDP2WInfoStore< CRGBContext>, public CStdDP2RenderStateStore< CRGBContext>, public CStdDP2TextureStageStateStore< CRGBContext>, public CStdDP2VStreamManager< CRGBContext, CVStream< CRGBDriver::TSurface*, CRGBDriver::TPerDDrawData::TSurfDBEntry*> >, public CStdDP2IStreamManager< CRGBContext, CIStream< CRGBDriver::TSurface*, CRGBDriver::TPerDDrawData::TSurfDBEntry*> >, public CStdDP2PaletteManager< CRGBContext, CPalDBEntry, static_hash_map< DWORD, CPalDBEntry, 4> > { public: // Types typedef TPerDDrawData::TDriver::TSurface TSurface; protected: // Types typedef block< TDP2CmdBind, 17> TDP2Bindings; typedef block< TRecDP2CmdBind, 7> TRecDP2Bindings; struct SHandleHasCaps: public unary_function< DWORD, bool> { const TPerDDrawData& m_PDDD; DWORD m_dwCaps; explicit SHandleHasCaps( const TPerDDrawData& PDDD, const DWORD dwCaps) throw(): m_PDDD( PDDD), m_dwCaps( dwCaps) { } result_type operator()( const argument_type Arg) const { const TPerDDrawData::TSurfDBEntry* pSurfDBEntry= m_PDDD.GetSurfDBEntry( Arg); assert( pSurfDBEntry!= NULL); return((pSurfDBEntry->GetLCLddsCaps().dwCaps& m_dwCaps)== m_dwCaps); } }; protected: static const TDP2Bindings c_DP2Bindings; static const TRecDP2Bindings c_RecDP2Bindings; D3DI_RASTCTX m_RastCtx; PrimProcessor m_PrimProc; D3DI_SPANTEX m_aSpanTex[8]; // FVF stuff FVFDATA m_fvfData; // Used to store the old last pixel setting when drawing line strips. UINT m_uFlags; static DWORD DetectBeadSet( void) throw(); static const UINT c_uiBegan; public: CRGBContext( TPerDDrawData& PDDD, PORTABLE_CONTEXTCREATEDATA& ccd): TSubContext( PDDD, ccd), TDrawPrimitives2( c_DP2Bindings.begin(), c_DP2Bindings.end(), c_RecDP2Bindings.begin(), c_RecDP2Bindings.end()), m_uFlags( 0) { HRESULT hr= m_PrimProc.Initialize(); assert( SUCCEEDED( hr)); // TODO: Can fail? // TODO: Remove this unextendable stuff? memset(&m_RastCtx, 0, sizeof(m_RastCtx)); m_RastCtx.dwSize = sizeof(D3DI_RASTCTX); m_RastCtx.pdwRenderState[ D3DRENDERSTATE_SCENECAPTURE]= FALSE; // Hit our notification scheme here. NewColorBuffer(); NewDepthBuffer(); m_PrimProc.SetCtx(&m_RastCtx); // Initialize bead table enum m_RastCtx.BeadSet = (D3DI_BEADSET)DetectBeadSet(); m_RastCtx.uDevVer = 0; // All render and texture stage state is initialized by // DIRECT3DDEVICEI::stateInitialize // Enable MMX Fast Paths (Monolithics) if a registry key for it is not 0 m_RastCtx.dwMMXFPDisableMask[0] = 0x0; // enable MMX FP's by default } ~CRGBContext() throw() { } void NewColorBuffer() { End(); TRTarget& ColorBuffer= GetColorBuffer(); if( ColorBuffer.GetMemLocation()!= TRTarget::EMemLocation::None) { IRGBSurface* pVMSurface= ColorBuffer.GetVidMemRepresentation(); m_RastCtx.iSurfaceStride= pVMSurface->GetGBLlPitch(); m_RastCtx.iSurfaceStep= pVMSurface->GetBytesPerPixel(); m_RastCtx.iSurfaceBitCount= m_RastCtx.iSurfaceStep* 8; m_RastCtx.iSurfaceType= pVMSurface->GetSpanTexFormat(); m_RastCtx.Clip.left= m_RastCtx.Clip.top= 0; m_RastCtx.Clip.bottom= pVMSurface->GetGBLwHeight(); m_RastCtx.Clip.right= pVMSurface->GetGBLwWidth(); m_RastCtx.pDDS= reinterpret_cast(pVMSurface); } else { m_RastCtx.iSurfaceStride= 0; m_RastCtx.iSurfaceStep= 0; m_RastCtx.iSurfaceBitCount= 0; m_RastCtx.iSurfaceType= D3DI_SPTFMT_NULL; m_RastCtx.Clip.left= m_RastCtx.Clip.top= 0; m_RastCtx.Clip.right= m_RastCtx.Clip.bottom= 0; m_RastCtx.pDDS= NULL; } TSubContext::NewColorBuffer(); } void NewDepthBuffer() { End(); TRTarget& DepthBuffer= GetDepthBuffer(); if( DepthBuffer.GetMemLocation()!= TRTarget::EMemLocation::None) { IRGBSurface* pVMSurface= DepthBuffer.GetVidMemRepresentation(); m_RastCtx.pZBits= NULL; m_RastCtx.iZStride= pVMSurface->GetGBLlPitch(); m_RastCtx.iZStep= pVMSurface->GetBytesPerPixel(); m_RastCtx.iZBitCount= m_RastCtx.iZStep* 8; m_RastCtx.pDDSZ= reinterpret_cast(pVMSurface); } else { m_RastCtx.pZBits= NULL; m_RastCtx.iZStride= 0; m_RastCtx.iZBitCount= 0; m_RastCtx.iZStep= 0; m_RastCtx.pDDSZ= NULL; } TSubContext::NewDepthBuffer(); } HRESULT DP2ViewportInfo( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) throw() { const D3DHAL_DP2VIEWPORTINFO* pParam= reinterpret_cast< const D3DHAL_DP2VIEWPORTINFO*>(pP); // TODO: Roll into RGBContext (This particularly into DX8SDDIFW). m_RastCtx.Clip.left = pParam->dwX; m_RastCtx.Clip.top = pParam->dwY; m_RastCtx.Clip.bottom = pParam->dwY + pParam->dwHeight; m_RastCtx.Clip.right = pParam->dwX + pParam->dwWidth; return DD_OK; } operator D3DHAL_DP2VIEWPORTINFO() const throw() { D3DHAL_DP2VIEWPORTINFO Ret; Ret.dwX= m_RastCtx.Clip.left; Ret.dwY= m_RastCtx.Clip.top; Ret.dwWidth= m_RastCtx.Clip.right- Ret.dwX; Ret.dwHeight= m_RastCtx.Clip.bottom- Ret.dwY; return Ret; } void GetDP2ViewportInfo( D3DHAL_DP2VIEWPORTINFO& Param) const throw() { Param= (*this); } HRESULT RecDP2ViewportInfo( const D3DHAL_DP2COMMAND* pCmd, void* pP) throw() { D3DHAL_DP2VIEWPORTINFO* pParam= reinterpret_cast< D3DHAL_DP2VIEWPORTINFO*>(pP); pParam->dwX= m_RastCtx.Clip.left; pParam->dwY= m_RastCtx.Clip.top; pParam->dwWidth= m_RastCtx.Clip.right- m_RastCtx.Clip.left; pParam->dwHeight= m_RastCtx.Clip.bottom- m_RastCtx.Clip.top; return DD_OK; } HRESULT SetRenderState( UINT32 uState, UINT32 uStateVal) { m_RastCtx.pdwRenderState[uState] = uStateVal; switch(uState) { case D3DRS_CULLMODE: // Set face culling sign from state. switch(uStateVal) { case D3DCULL_CCW: m_RastCtx.uCullFaceSign= 1; break; case D3DCULL_CW: m_RastCtx.uCullFaceSign= 0; break; case D3DCULL_NONE: m_RastCtx.uCullFaceSign= 2; break; } break; case D3DRS_LASTPIXEL: // Set last-pixel flag from state. if (uStateVal) { m_PrimProc.SetFlags(PPF_DRAW_LAST_LINE_PIXEL); } else { m_PrimProc.ClrFlags(PPF_DRAW_LAST_LINE_PIXEL); } break; default: break; } return DD_OK; } HRESULT DP2RenderState( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { const D3DHAL_DP2RENDERSTATE* pParam= reinterpret_cast(pP); WORD wStateCount( pCmd->wStateCount); HRESULT hr( DD_OK); End(); D3DHAL_DP2RENDERSTATE SCap; SCap.RenderState= static_cast< D3DRENDERSTATETYPE>( D3DRENDERSTATE_SCENECAPTURE); GetDP2RenderState( SCap); const DWORD dwOldSC( SCap.dwState); if((DP2Data.dwFlags()& D3DHALDP2_EXECUTEBUFFER)!= 0) { // dp2d.lpdwRStates should be valid. if( wStateCount) do { assert( pParam->RenderState< D3DHAL_MAX_RSTATES); hr= SetRenderState( pParam->RenderState, pParam->dwState); if( SUCCEEDED(hr)) DP2Data.lpdwRStates()[ pParam->RenderState]= pParam->dwState; ++pParam; } while( SUCCEEDED(hr)&& --wStateCount); } else { if( wStateCount) do { assert( pParam->RenderState< D3DHAL_MAX_RSTATES); hr= SetRenderState( pParam->RenderState, pParam->dwState); ++pParam; } while( SUCCEEDED(hr)&& --wStateCount); } GetDP2RenderState( SCap); if( FALSE== dwOldSC && TRUE== SCap.dwState) OnSceneCaptureStart(); else if( TRUE== dwOldSC && FALSE== SCap.dwState) OnSceneCaptureEnd(); return hr; } DWORD GetRenderStateDW( D3DRENDERSTATETYPE RS) const throw() { assert( RS< D3DHAL_MAX_RSTATES); return m_RastCtx.pdwRenderState[ RS]; } D3DVALUE GetRenderStateDV( D3DRENDERSTATETYPE RS) const throw() { assert( RS< D3DHAL_MAX_RSTATES); return *(reinterpret_cast< const D3DVALUE*>( &m_RastCtx.pfRenderState[ RS])); } void GetDP2RenderState( D3DHAL_DP2RENDERSTATE& GetParam) const throw() { GetParam.dwState= GetRenderStateDW( GetParam.RenderState); } void OnSceneCaptureStart( void) throw() { #if defined(USE_ICECAP4) static bool bStarted( true); if( bStarted) StopProfile( PROFILE_THREADLEVEL, PROFILE_CURRENTID); else StartProfile( PROFILE_THREADLEVEL, PROFILE_CURRENTID); bStarted= !bStarted; CommentMarkProfile( 1, "SceneCaptureStart"); #endif } void OnSceneCaptureEnd( void) throw() { #if defined(USE_ICECAP4) CommentMarkProfile( 2, "SceneCaptureEnd"); // StopProfile( PROFILE_THREADLEVEL, PROFILE_CURRENTID); #endif End(); } void OnEndDrawPrimitives2( TDP2Data& ) { End(); } HRESULT SetTextureStageState( DWORD dwStage, DWORD dwState, DWORD uStateVal) { UINT cNewActTex = 0; m_RastCtx.pdwTextureStageState[dwStage][dwState] = uStateVal; switch (dwState) { case D3DTSS_TEXTUREMAP: { const TPerDDrawData::TSurfDBEntry* pTexDBEntry= GetPerDDrawData().GetSurfDBEntry( uStateVal); if( pTexDBEntry!= NULL) { assert((pTexDBEntry->GetLCLddsCaps().dwCaps& DDSCAPS_TEXTURE)!= 0); memset( &m_aSpanTex[ dwStage], 0, sizeof(m_aSpanTex[0])); m_aSpanTex[ dwStage].dwSize= sizeof(m_aSpanTex[0]); m_RastCtx.pTexture[ dwStage]= &m_aSpanTex[ dwStage]; // Appears that a unique num is needed, but looks like // field isn't used anywhere. Using handle... m_aSpanTex[ dwStage].iGeneration= uStateVal; assert((pTexDBEntry->GetLCLdwFlags()& DDRAWISURF_HASCKEYSRCBLT)== 0); m_aSpanTex[ dwStage].uFlags&= ~D3DI_SPANTEX_HAS_TRANSPARENT; m_aSpanTex[ dwStage].Format= ConvPixelFormat( pTexDBEntry->GetGBLddpfSurface()); if( m_aSpanTex[ dwStage].Format== D3DI_SPTFMT_PALETTE8 || m_aSpanTex[ dwStage].Format== D3DI_SPTFMT_PALETTE4) { TPalDBEntry* pPalDBEntry= pTexDBEntry->GetPalette(); assert( pPalDBEntry!= NULL); if((pPalDBEntry->GetFlags()& DDRAWIPAL_ALPHA)!= 0) m_aSpanTex[ dwStage].uFlags|= D3DI_SPANTEX_ALPHAPALETTE; m_aSpanTex[ dwStage].pPalette= reinterpret_cast( pPalDBEntry->GetEntries()); if( m_aSpanTex[ dwStage].Format== D3DI_SPTFMT_PALETTE8) m_aSpanTex[ dwStage].iPaletteSize = 256; else { // PALETTE4 m_aSpanTex[ dwStage].iPaletteSize = 16; } } m_aSpanTex[ dwStage].TexAddrU= D3DTADDRESS_WRAP; m_aSpanTex[ dwStage].TexAddrV= D3DTADDRESS_WRAP; m_aSpanTex[ dwStage].BorderColor= RGBA_MAKE(0xff, 0x00, 0xff, 0xff); // assign first pSurf here (mipmap chain gets assigned below) m_aSpanTex[ dwStage].pSurf[0]= (LPDIRECTDRAWSURFACE)(pTexDBEntry); // Check for mipmap if any. const TPerDDrawData::TSurfDBEntry* pLcl= pTexDBEntry; // iPreSizeU and iPreSizeV store the size(u and v) of the previous level // mipmap. They are init'ed with the first texture size. INT16 iPreSizeU = m_aSpanTex[ dwStage].iSizeU, iPreSizeV = m_aSpanTex[ dwStage].iSizeV; for (;;) { TPerDDrawData::TSurfDBEntry::THandleVector::const_iterator itNextTexHandle; itNextTexHandle= find_if( pLcl->GetAttachedTo().begin(), pLcl->GetAttachedTo().end(), SHandleHasCaps( GetPerDDrawData(), DDSCAPS_TEXTURE)); if( pLcl->GetAttachedTo().end()== itNextTexHandle) break; pLcl= GetPerDDrawData().GetSurfDBEntry( *itNextTexHandle); assert( pLcl!= NULL); m_aSpanTex[ dwStage].cLODTex++; m_aSpanTex[ dwStage].pSurf[m_aSpanTex[ dwStage].cLODTex]= (LPDIRECTDRAWSURFACE)pLcl; } SetSizesSpanTexture( &m_aSpanTex[ dwStage]); } else m_RastCtx.pTexture[ dwStage]= NULL; if( m_RastCtx.pTexture[dwStage]!= NULL) { m_RastCtx.pTexture[dwStage]->TexAddrU= (D3DTEXTUREADDRESS)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSU]); m_RastCtx.pTexture[dwStage]->TexAddrV= (D3DTEXTUREADDRESS)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSV]); m_RastCtx.pTexture[dwStage]->BorderColor= (D3DCOLOR)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_BORDERCOLOR]); m_RastCtx.pTexture[dwStage]->uMagFilter= (D3DTEXTUREMAGFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAGFILTER]); m_RastCtx.pTexture[dwStage]->uMinFilter= (D3DTEXTUREMINFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MINFILTER]); m_RastCtx.pTexture[dwStage]->uMipFilter= (D3DTEXTUREMIPFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MIPFILTER]); m_RastCtx.pTexture[dwStage]->fLODBias= m_RastCtx.pfTextureStageState[dwStage][D3DTSS_MIPMAPLODBIAS]; if( m_RastCtx.pTexture[dwStage]->iMaxMipLevel!= (INT32)m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAXMIPLEVEL]) { m_RastCtx.pTexture[dwStage]->iMaxMipLevel= (INT32)m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAXMIPLEVEL]; m_RastCtx.pTexture[dwStage]->uFlags|= D3DI_SPANTEX_MAXMIPLEVELS_DIRTY; } } // conservative but correct D3DHAL_VALIDATETEXTURESTAGESTATEDATA FakeVTSSD; FakeVTSSD.dwhContext= reinterpret_cast< ULONG_PTR>(this); FakeVTSSD.dwFlags= 0; FakeVTSSD.dwReserved= 0; FakeVTSSD.dwNumPasses= 0; FakeVTSSD.ddrval= DD_OK; if((FakeVTSSD.ddrval= ValidateTextureStageState( FakeVTSSD))== DD_OK) { // count number of contiguous-from-zero active texture blend stages for( INT iStage=0; iStage< D3DHAL_TSS_MAXSTAGES; iStage++) { // check for disabled stage (subsequent are thus inactive) // also conservatively checks for incorrectly enabled stage (might be legacy) if((m_RastCtx.pdwTextureStageState[iStage][D3DTSS_COLOROP]== D3DTOP_DISABLE) || (m_RastCtx.pTexture[iStage]== NULL)) { break; } // stage is active cNewActTex++; } } if( m_RastCtx.cActTex!= cNewActTex) { m_RastCtx.StatesDirtyBits[D3DRENDERSTATE_TEXTUREHANDLE>>3]|= (1<<(D3DRENDERSTATE_TEXTUREHANDLE& 7)); m_RastCtx.StatesDirtyBits[D3DHAL_MAX_RSTATES_AND_STAGES>>3]|= (1<<(D3DHAL_MAX_RSTATES_AND_STAGES& 7)); m_RastCtx.cActTex= cNewActTex; } break; } case D3DTSS_ADDRESSU: case D3DTSS_ADDRESSV: case D3DTSS_MIPMAPLODBIAS: case D3DTSS_MAXMIPLEVEL: case D3DTSS_BORDERCOLOR: case D3DTSS_MAGFILTER: case D3DTSS_MINFILTER: case D3DTSS_MIPFILTER: if( m_RastCtx.pTexture[dwStage]!= NULL) { m_RastCtx.pTexture[dwStage]->TexAddrU= (D3DTEXTUREADDRESS)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSU]); m_RastCtx.pTexture[dwStage]->TexAddrV= (D3DTEXTUREADDRESS)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_ADDRESSV]); m_RastCtx.pTexture[dwStage]->BorderColor= (D3DCOLOR)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_BORDERCOLOR]); m_RastCtx.pTexture[dwStage]->uMagFilter= (D3DTEXTUREMAGFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAGFILTER]); m_RastCtx.pTexture[dwStage]->uMinFilter= (D3DTEXTUREMINFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MINFILTER]); m_RastCtx.pTexture[dwStage]->uMipFilter= (D3DTEXTUREMIPFILTER)(m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MIPFILTER]); m_RastCtx.pTexture[dwStage]->fLODBias= m_RastCtx.pfTextureStageState[dwStage][D3DTSS_MIPMAPLODBIAS]; if( m_RastCtx.pTexture[dwStage]->iMaxMipLevel!= (INT32)m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAXMIPLEVEL]) { m_RastCtx.pTexture[dwStage]->iMaxMipLevel= (INT32)m_RastCtx.pdwTextureStageState[dwStage][D3DTSS_MAXMIPLEVEL]; m_RastCtx.pTexture[dwStage]->uFlags|= D3DI_SPANTEX_MAXMIPLEVELS_DIRTY; } } break; case D3DTSS_COLOROP: case D3DTSS_COLORARG1: case D3DTSS_COLORARG2: case D3DTSS_ALPHAOP: case D3DTSS_ALPHAARG1: case D3DTSS_ALPHAARG2: { // anything that effects the validity of the texture blending // could change the number of active texture stages // conservative but correct D3DHAL_VALIDATETEXTURESTAGESTATEDATA FakeVTSSD; FakeVTSSD.dwhContext= reinterpret_cast< ULONG_PTR>(this); FakeVTSSD.dwFlags= 0; FakeVTSSD.dwReserved= 0; FakeVTSSD.dwNumPasses= 0; FakeVTSSD.ddrval= DD_OK; if((FakeVTSSD.ddrval= ValidateTextureStageState( FakeVTSSD))== DD_OK) { // count number of contiguous-from-zero active texture blend stages for( INT iStage=0; iStage< D3DHAL_TSS_MAXSTAGES; iStage++) { // check for disabled stage (subsequent are thus inactive) // also conservatively checks for incorrectly enabled stage (might be legacy) if((m_RastCtx.pdwTextureStageState[iStage][D3DTSS_COLOROP]== D3DTOP_DISABLE) || (m_RastCtx.pTexture[iStage]== NULL)) { break; } // stage is active cNewActTex++; } } m_RastCtx.cActTex= cNewActTex; break; } } return DD_OK; } HRESULT DP2TextureStageState( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { const D3DHAL_DP2TEXTURESTAGESTATE* pParam= reinterpret_cast(pP); WORD wStateCount( pCmd->wStateCount); HRESULT hr( DD_OK); End(); if( wStateCount) do { assert( pParam->TSState< D3DTSS_MAX); hr= SetTextureStageState( pParam->wStage, pParam->TSState, pParam->dwValue); ++pParam; } while( SUCCEEDED(hr)&& --wStateCount); return hr; } DWORD GetTextureStageStateDW( WORD wStage, WORD wTSState) const throw() { return m_RastCtx.pdwTextureStageState[ wStage][ wTSState]; } D3DVALUE GetTextureStageStateDV( WORD wStage, WORD wTSState) const throw() { return *(reinterpret_cast< const D3DVALUE*>( &m_RastCtx.pdwTextureStageState[ wStage][ wTSState])); } void GetDP2TextureStageState( D3DHAL_DP2TEXTURESTAGESTATE& GetParam) const throw() { GetParam.dwValue= GetTextureStageStateDW( GetParam.wStage, GetParam.TSState); } HRESULT ValidateTextureStageState( D3DHAL_VALIDATETEXTURESTAGESTATEDATA& vtssd) const throw() { vtssd.dwNumPasses= 1; if ((m_RastCtx.pTexture[0] == m_RastCtx.pTexture[1]) && (m_RastCtx.pTexture[0] != NULL) ) { // except under very special circumstances, this will not work in RGB/MMX // since we keep a lot of stage state in the D3DI_SPANTEX structure return D3DERR_TOOMANYOPERATIONS; } for (INT i = 0; i < D3DHAL_TSS_MAXSTAGES; i++) { switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_COLOROP]) { default: return D3DERR_UNSUPPORTEDCOLOROPERATION; case D3DTOP_DISABLE: return DD_OK; // don't have to validate further if the stage is disabled case D3DTOP_SELECTARG1: case D3DTOP_SELECTARG2: case D3DTOP_MODULATE: case D3DTOP_MODULATE2X: case D3DTOP_MODULATE4X: case D3DTOP_ADD: case D3DTOP_ADDSIGNED: case D3DTOP_BLENDDIFFUSEALPHA: case D3DTOP_BLENDTEXTUREALPHA: case D3DTOP_BLENDFACTORALPHA: case D3DTOP_BLENDTEXTUREALPHAPM: case D3DTOP_ADDSIGNED2X: case D3DTOP_SUBTRACT: case D3DTOP_ADDSMOOTH: case D3DTOP_MODULATEALPHA_ADDCOLOR: case D3DTOP_MODULATECOLOR_ADDALPHA: break; } switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_COLORARG1] & ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT)) { default: return D3DERR_UNSUPPORTEDCOLORARG; case (D3DTA_TEXTURE): break; } switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_COLORARG2] & ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT)) { default: return D3DERR_UNSUPPORTEDCOLORARG; case (D3DTA_TFACTOR): case (D3DTA_CURRENT): case (D3DTA_DIFFUSE): case (D3DTA_SPECULAR): break; } switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_ALPHAOP]) { default: return D3DERR_UNSUPPORTEDALPHAOPERATION; case D3DTOP_DISABLE: break; case D3DTOP_SELECTARG1: case D3DTOP_SELECTARG2: case D3DTOP_MODULATE: case D3DTOP_MODULATE2X: case D3DTOP_MODULATE4X: case D3DTOP_ADD: case D3DTOP_ADDSIGNED: case D3DTOP_BLENDDIFFUSEALPHA: case D3DTOP_BLENDTEXTUREALPHA: case D3DTOP_BLENDFACTORALPHA: case D3DTOP_BLENDTEXTUREALPHAPM: case D3DTOP_ADDSIGNED2X: case D3DTOP_SUBTRACT: case D3DTOP_ADDSMOOTH: // only validate alpha args if alpha op is not disable switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_ALPHAARG1] & ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT)) { default: return D3DERR_UNSUPPORTEDALPHAARG; case (D3DTA_TEXTURE): break; } switch(m_RastCtx.pdwTextureStageState[i][D3DTSS_ALPHAARG2] & ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT)) { default: return D3DERR_UNSUPPORTEDALPHAARG; case (D3DTA_TFACTOR): case (D3DTA_CURRENT): case (D3DTA_DIFFUSE): case (D3DTA_SPECULAR): break; } break; } } return DD_OK; } HRESULT DP2Clear( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { End(); return TSubContext::DP2Clear( DP2Data, pCmd, pP); } HRESULT CheckFVF(DWORD dwFVF) { // check if FVF controls have changed if ( (m_fvfData.preFVF == dwFVF) && (m_fvfData.TexIdx[0] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[0][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.TexIdx[1] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[1][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.TexIdx[2] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[2][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.TexIdx[3] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[3][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.TexIdx[4] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[4][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.TexIdx[5] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[5][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.TexIdx[6] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[6][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.TexIdx[7] == (INT)(0xffff&m_RastCtx.pdwTextureStageState[7][D3DTSS_TEXCOORDINDEX])) && (m_fvfData.cActTex == m_RastCtx.cActTex) ) { return D3D_OK; } memset(&m_fvfData, 0, sizeof(FVFDATA)); m_fvfData.preFVF = dwFVF; INT32 i; for ( i = 0; i < D3DHAL_TSS_MAXSTAGES; i++) { m_fvfData.TexIdx[i] = 0xffff&m_RastCtx.pdwTextureStageState[i][D3DTSS_TEXCOORDINDEX]; } m_fvfData.cActTex = m_RastCtx.cActTex; // XYZ if ( (dwFVF & (D3DFVF_RESERVED0 | D3DFVF_RESERVED2 | D3DFVF_NORMAL)) || ((dwFVF & (D3DFVF_XYZ | D3DFVF_XYZRHW)) == 0) ) { // can't set reserved bits, shouldn't have normals in // output to rasterizers, and must have coordinates return DDERR_INVALIDPARAMS; } m_fvfData.stride = sizeof(D3DVALUE) * 3; if (dwFVF & D3DFVF_XYZRHW) { m_fvfData.offsetRHW = m_fvfData.stride; m_fvfData.stride += sizeof(D3DVALUE); } if (dwFVF & D3DFVF_PSIZE) { m_fvfData.offsetPSize = m_fvfData.stride; m_fvfData.stride += sizeof(D3DVALUE); } if (dwFVF & D3DFVF_DIFFUSE) { m_fvfData.offsetDiff = m_fvfData.stride; m_fvfData.stride += sizeof(D3DCOLOR); } if (dwFVF & D3DFVF_SPECULAR) { m_fvfData.offsetSpec = m_fvfData.stride; m_fvfData.stride += sizeof(D3DCOLOR); } INT iTexCount = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; if (iTexCount > 0) { // set offset for Textures for ( i = 0; i < D3DHAL_TSS_MAXSTAGES; i ++) { m_fvfData.offsetTex[i] = (SHORT)(m_fvfData.stride + 2*sizeof(D3DVALUE)*m_fvfData.TexIdx[i]); } // update stride m_fvfData.stride += (USHORT)(iTexCount * (sizeof(D3DVALUE) * 2)); } if( D3DFVF_TLVERTEX== dwFVF) m_fvfData.vtxType = RAST_TLVERTEX; else m_fvfData.vtxType = RAST_GENVERTEX; return D3D_OK; } void PackGenVertex(PUINT8 pFvfVtx, RAST_GENERIC_VERTEX *pGenVtx) { pGenVtx->sx = *((D3DVALUE *)pFvfVtx); pGenVtx->sy = *((D3DVALUE *)pFvfVtx + 1); pGenVtx->sz = *((D3DVALUE *)pFvfVtx + 2); if (m_fvfData.offsetRHW) { pGenVtx->rhw = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetRHW)); } else { pGenVtx->rhw = 1.0f; } if (m_fvfData.offsetDiff) { pGenVtx->color = *((D3DCOLOR *)(pFvfVtx + m_fvfData.offsetDiff)); } else { pGenVtx->color = 0xFFFFFFFF; //__DEFAULT_DIFFUSE; } if (m_fvfData.offsetSpec) { pGenVtx->specular = *((D3DCOLOR *)(pFvfVtx + m_fvfData.offsetSpec)); } else { pGenVtx->specular = 0; //__DEFAULT_SPECULAR; } for (INT32 i = 0; i < (INT32)m_fvfData.cActTex; i++) { if (m_fvfData.offsetTex[i]) { pGenVtx->texCoord[i].tu = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex[i])); pGenVtx->texCoord[i].tv = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex[i]) + 1); } else { pGenVtx->texCoord[i].tu = 0.0f; pGenVtx->texCoord[i].tv = 0.0f; } } } HRESULT DP2DrawPrimitive( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { const D3DHAL_DP2DRAWPRIMITIVE* pParam= reinterpret_cast< const D3DHAL_DP2DRAWPRIMITIVE*>(pP); HRESULT hr( DD_OK); const D3DHAL_DP2VERTEXSHADER VertexShader(*this); // We need this data. UINT8* pStartVData= NULL; DWORD dwVStride( 0); // Since RGB is a non TnL device, the vertex shader handle should // always be a fixed function FVF. const DWORD dwFVF( VertexShader.dwHandle); // Since RGB only supports one stream, our data source should be // from stream 0. TVStream& VStream0( m_VStreamDB[ 0]); VStream0.SetFVF( dwFVF); // Find vertex information. if( VStream0.GetMemLocation()== TVStream::EMemLocation::User) { pStartVData= reinterpret_cast< UINT8*>( VStream0.GetUserMemPtr()); dwVStride= VStream0.GetStride(); } else if( VStream0.GetMemLocation()== TVStream::EMemLocation::System|| VStream0.GetMemLocation()== TVStream::EMemLocation::Video) { // RGB can pretend system mem and video mem surfaces are the same. pStartVData= reinterpret_cast< UINT8*>( VStream0.GetSurfDBRepresentation()->GetGBLfpVidMem()); dwVStride= VStream0.GetStride(); } if( pStartVData!= NULL) { Begin(); WORD wPrimitiveCount( pCmd->wPrimitiveCount); hr= CheckFVF( dwFVF); assert( SUCCEEDED( hr)); if( FAILED( hr)) wPrimitiveCount= 0; if( wPrimitiveCount) do { UINT8* pVData= pStartVData+ pParam->VStart* dwVStride; m_PrimProc.BeginPrimSet( pParam->primType, m_fvfData.vtxType); if( RAST_GENVERTEX== m_fvfData.vtxType) DoDrawOneGenPrimitive( dwVStride, pVData, pParam->primType, pParam->PrimitiveCount); else DoDrawOnePrimitive( dwVStride, pVData, pParam->primType, pParam->PrimitiveCount); } while( SUCCEEDED(hr) && --wPrimitiveCount); } return hr; } HRESULT DP2DrawPrimitive2( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { const D3DHAL_DP2DRAWPRIMITIVE2* pParam= reinterpret_cast< const D3DHAL_DP2DRAWPRIMITIVE2*>(pP); HRESULT hr( DD_OK); const D3DHAL_DP2VERTEXSHADER VertexShader(*this); // We need this data. UINT8* pStartVData= NULL; DWORD dwVStride( 0); // Since RGB is a non TnL device, the vertex shader handle should // always be a fixed function FVF. const DWORD dwFVF( VertexShader.dwHandle); // Since RGB only supports one stream, our data source should be // from stream 0. TVStream& VStream0( m_VStreamDB[ 0]); VStream0.SetFVF( dwFVF); // Find vertex information. if( VStream0.GetMemLocation()== TVStream::EMemLocation::User) { pStartVData= reinterpret_cast< UINT8*>( VStream0.GetUserMemPtr()); dwVStride= VStream0.GetStride(); } else if( VStream0.GetMemLocation()== TVStream::EMemLocation::System|| VStream0.GetMemLocation()== TVStream::EMemLocation::Video) { // RGB can pretend system mem and video mem surfaces are the same. pStartVData= reinterpret_cast< UINT8*>( VStream0.GetSurfDBRepresentation()->GetGBLfpVidMem()); dwVStride= VStream0.GetStride(); } if( pStartVData!= NULL) { Begin(); WORD wPrimitiveCount( pCmd->wPrimitiveCount); hr= CheckFVF( dwFVF); assert( SUCCEEDED( hr)); if( FAILED( hr)) wPrimitiveCount= 0; if( wPrimitiveCount) do { UINT8* pVData= pStartVData+ pParam->FirstVertexOffset; m_PrimProc.BeginPrimSet( pParam->primType, m_fvfData.vtxType); if( RAST_GENVERTEX== m_fvfData.vtxType) DoDrawOneGenPrimitive( dwVStride, pVData, pParam->primType, pParam->PrimitiveCount); else DoDrawOnePrimitive( dwVStride, pVData, pParam->primType, pParam->PrimitiveCount); } while( SUCCEEDED(hr) && --wPrimitiveCount); } return hr; } HRESULT DP2DrawIndexedPrimitive( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { const D3DHAL_DP2DRAWINDEXEDPRIMITIVE* pParam= reinterpret_cast< const D3DHAL_DP2DRAWINDEXEDPRIMITIVE*>(pP); HRESULT hr( DD_OK); const D3DHAL_DP2VERTEXSHADER VertexShader(*this); // We need this data for rasterization. UINT8* pStartVData= NULL; UINT8* pStartIData= NULL; DWORD dwVStride( 0); DWORD dwIStride( 0); // Since RGB is a non TnL device, the vertex shader handle should // always be a fixed function FVF. const DWORD dwFVF( VertexShader.dwHandle); // Since RGB only supports one stream, our data source should be // from stream 0. TVStream& VStream0( m_VStreamDB[ 0]); VStream0.SetFVF( dwFVF); // Find vertex information. if( VStream0.GetMemLocation()== TVStream::EMemLocation::User) { pStartVData= reinterpret_cast< UINT8*>( VStream0.GetUserMemPtr()); dwVStride= VStream0.GetStride(); } else if( VStream0.GetMemLocation()== TVStream::EMemLocation::System|| VStream0.GetMemLocation()== TVStream::EMemLocation::Video) { // RGB can pretend system mem and video mem surfaces are the same. pStartVData= reinterpret_cast< UINT8*>( VStream0.GetSurfDBRepresentation()->GetGBLfpVidMem()); dwVStride= VStream0.GetStride(); } // Find Indices information. const TIStream& IStream= GetIStream( 0); if( IStream.GetMemLocation()== TIStream::EMemLocation::System|| IStream.GetMemLocation()== TIStream::EMemLocation::Video) { // RGB can pretend system mem and video mem surfaces are the same. pStartIData= reinterpret_cast< UINT8*>( IStream.GetSurfDBRepresentation()->GetGBLfpVidMem()); dwIStride= IStream.GetStride(); } if( pStartVData!= NULL&& pStartIData!= NULL&& sizeof(WORD)== dwIStride) { Begin(); WORD wPrimitiveCount( pCmd->wPrimitiveCount); hr= CheckFVF( dwFVF); assert( SUCCEEDED( hr)); if( FAILED( hr)) wPrimitiveCount= 0; if( wPrimitiveCount) do { UINT8* pVData= pStartVData+ pParam->BaseVertexIndex* dwVStride; UINT8* pIData= pStartIData+ pParam->StartIndex* dwIStride; m_PrimProc.BeginPrimSet( pParam->primType, m_fvfData.vtxType); if( RAST_GENVERTEX== m_fvfData.vtxType) DoDrawOneGenIndexedPrimitive( dwVStride, pVData, reinterpret_cast(pIData), pParam->primType, pParam->PrimitiveCount); else DoDrawOneIndexedPrimitive( dwVStride, pVData, reinterpret_cast(pIData), pParam->primType, pParam->PrimitiveCount); } while( SUCCEEDED(hr) && --wPrimitiveCount); } return hr; } HRESULT DP2DrawIndexedPrimitive2( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { const D3DHAL_DP2DRAWINDEXEDPRIMITIVE2* pParam= reinterpret_cast< const D3DHAL_DP2DRAWINDEXEDPRIMITIVE2*>(pP); HRESULT hr( DD_OK); const D3DHAL_DP2VERTEXSHADER VertexShader(*this); // We need this data for rasterization. UINT8* pStartVData= NULL; UINT8* pStartIData= NULL; DWORD dwVStride( 0); DWORD dwIStride( 0); // Since RGB is a non TnL device, the vertex shader handle should // always be a fixed function FVF. const DWORD dwFVF( VertexShader.dwHandle); // Since RGB only supports one stream, our data source should be // from stream 0. TVStream& VStream0( m_VStreamDB[ 0]); VStream0.SetFVF( dwFVF); // Find vertex information. if( VStream0.GetMemLocation()== TVStream::EMemLocation::User) { pStartVData= reinterpret_cast< UINT8*>( VStream0.GetUserMemPtr()); dwVStride= VStream0.GetStride(); } else if( VStream0.GetMemLocation()== TVStream::EMemLocation::System|| VStream0.GetMemLocation()== TVStream::EMemLocation::Video) { // RGB can pretend system mem and video mem surfaces are the same. pStartVData= reinterpret_cast< UINT8*>( VStream0.GetSurfDBRepresentation()->GetGBLfpVidMem()); dwVStride= VStream0.GetStride(); } // Find Indices information. const TIStream& IStream= GetIStream( 0); if( IStream.GetMemLocation()== TIStream::EMemLocation::System|| IStream.GetMemLocation()== TIStream::EMemLocation::Video) { // RGB can pretend system mem and video mem surfaces are the same. pStartIData= reinterpret_cast< UINT8*>( IStream.GetSurfDBRepresentation()->GetGBLfpVidMem()); dwIStride= IStream.GetStride(); } if( pStartVData!= NULL&& pStartIData!= NULL&& sizeof(WORD)== dwIStride) { Begin(); WORD wPrimitiveCount( pCmd->wPrimitiveCount); hr= CheckFVF( dwFVF); assert( SUCCEEDED( hr)); if( FAILED( hr)) wPrimitiveCount= 0; if( wPrimitiveCount) do { UINT8* pVData= pStartVData+ pParam->BaseVertexOffset; UINT8* pIData= pStartIData+ pParam->StartIndexOffset; m_PrimProc.BeginPrimSet( pParam->primType, m_fvfData.vtxType); if( RAST_GENVERTEX== m_fvfData.vtxType) DoDrawOneGenIndexedPrimitive( dwVStride, pVData, reinterpret_cast(pIData), pParam->primType, pParam->PrimitiveCount); else DoDrawOneIndexedPrimitive( dwVStride, pVData, reinterpret_cast(pIData), pParam->primType, pParam->PrimitiveCount); } while( SUCCEEDED(hr) && --wPrimitiveCount); } return hr; } HRESULT DP2ClippedTriangleFan( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd, const void* pP) { const D3DHAL_CLIPPEDTRIANGLEFAN* pParam= reinterpret_cast< const D3DHAL_CLIPPEDTRIANGLEFAN*>(pP); HRESULT hr( DD_OK); const D3DHAL_DP2VERTEXSHADER VertexShader(*this); // We need this data. UINT8* pStartVData= NULL; DWORD dwVStride( 0); // Since RGB is a non TnL device, the vertex shader handle should // always be a fixed function FVF. const DWORD dwFVF( VertexShader.dwHandle); // Since RGB only supports one stream, our data source should be // from stream 0. TVStream& VStream0( m_VStreamDB[ 0]); VStream0.SetFVF( dwFVF); // Find vertex information. if( VStream0.GetMemLocation()== TVStream::EMemLocation::User) { pStartVData= reinterpret_cast< UINT8*>( VStream0.GetUserMemPtr()); dwVStride= VStream0.GetStride(); } else if( VStream0.GetMemLocation()== TVStream::EMemLocation::System|| VStream0.GetMemLocation()== TVStream::EMemLocation::Video) { // RGB can pretend system mem and video mem surfaces are the same. pStartVData= reinterpret_cast< UINT8*>( VStream0.GetSurfDBRepresentation()->GetGBLfpVidMem()); dwVStride= VStream0.GetStride(); } if( pStartVData!= NULL) { Begin(); WORD wPrimitiveCount( pCmd->wPrimitiveCount); hr= CheckFVF( dwFVF); assert( SUCCEEDED( hr)); if( FAILED( hr)) wPrimitiveCount= 0; if( wPrimitiveCount) do { UINT8* pVData= pStartVData+ pParam->FirstVertexOffset; m_PrimProc.BeginPrimSet( D3DPT_TRIANGLEFAN, m_fvfData.vtxType); if( RAST_GENVERTEX== m_fvfData.vtxType) DoDrawOneGenEdgeFlagTriangleFan( dwVStride, pVData, pParam->PrimitiveCount, pParam->dwEdgeFlags); else DoDrawOneEdgeFlagTriangleFan( dwVStride, pVData, pParam->PrimitiveCount, pParam->dwEdgeFlags); } while( SUCCEEDED(hr) && --wPrimitiveCount); } return hr; } void Begin() { HRESULT hr( DD_OK); if((m_uFlags& c_uiBegan)!= 0) return; // TODO: call this less often? UpdateColorKeyAndPalette(); // Check for state changes BOOL bMaxMipLevelsDirty = FALSE; for (INT j = 0; j < (INT)m_RastCtx.cActTex; j++) { PD3DI_SPANTEX pSpanTex = m_RastCtx.pTexture[j]; if (pSpanTex) { bMaxMipLevelsDirty = bMaxMipLevelsDirty || (pSpanTex->uFlags & D3DI_SPANTEX_MAXMIPLEVELS_DIRTY); } } RastLockSpanTexture(); // Notify primitive Processor of state change. m_PrimProc.StateChanged(); // Must call SpanInit AFTER texture is locked, since this // sets various flags and fields that are needed for bead choosing // Call SpanInit to setup the beads hr= SpanInit(&m_RastCtx); // Lock rendering target (must be VM Surfaces). m_RastCtx.pSurfaceBits= reinterpret_cast( reinterpret_cast< TSurface*>(m_RastCtx.pDDS)->Lock( 0, NULL)); if( m_RastCtx.pDDSZ!= NULL) { m_RastCtx.pZBits= reinterpret_cast( reinterpret_cast< TSurface*>(m_RastCtx.pDDSZ)->Lock( 0, NULL)); } else { m_RastCtx.pZBits = NULL; } // Prepare the primitive processor m_PrimProc.Begin(); m_uFlags|= c_uiBegan; } void End( void) { if((m_uFlags& c_uiBegan)!= 0) { HRESULT hr = m_PrimProc.End(); assert( SUCCEEDED( hr)); // Unlock texture if this is not called in the middle of drawPrims to // flush for possible state changes. In the 2nd case, let // SetRenderState to handle it. RastUnlockSpanTexture(); // Unlock surfaces reinterpret_cast(m_RastCtx.pDDS)->Unlock(); if( m_RastCtx.pDDSZ!= NULL) reinterpret_cast(m_RastCtx.pDDSZ)->Unlock(); m_uFlags&= ~c_uiBegan; } } bool IsTextureOff(void) { return (m_RastCtx.cActTex == 0 || (m_RastCtx.cActTex == 1 && m_RastCtx.pTexture[0] == NULL) || (m_RastCtx.cActTex == 2 && (m_RastCtx.pTexture[0] == NULL || m_RastCtx.pTexture[1] == NULL))); } void RastUnlockSpanTexture(void) { INT i, j; PD3DI_SPANTEX pSpanTex;; if (IsTextureOff()) { return; } for (j = 0; j < (INT)m_RastCtx.cActTex; j++) { pSpanTex = m_RastCtx.pTexture[j]; INT iFirstSurf = min(pSpanTex->iMaxMipLevel, pSpanTex->cLODTex); // RastUnlock is used for cleanup in RastLock so it needs to // be able to handle partially locked mipmap chains. if((pSpanTex->uFlags& D3DI_SPANTEX_SURFACES_LOCKED)!= 0) { for (i = iFirstSurf; i <= pSpanTex->cLODTex; i++) { const TPerDDrawData::TSurfDBEntry* pSurfDBEntry= reinterpret_cast( pSpanTex->pSurf[i]); if((pSurfDBEntry->GetLCLddsCaps().dwCaps& DDSCAPS_VIDEOMEMORY)!= 0) { TSurface* pSurf= GetPerDDrawData().GetDriver().GetSurface( *pSurfDBEntry); pSurf->Unlock(); pSpanTex->pBits[i-iFirstSurf]= NULL; } } pSpanTex->uFlags&= ~D3DI_SPANTEX_SURFACES_LOCKED; } } } UINT32 static IntLog2(UINT32 x) { UINT32 y = 0; x >>= 1; while(x != 0) { x >>= 1; y++; } return y; } static HRESULT SetSizesSpanTexture(PD3DI_SPANTEX pSpanTex) { const TPerDDrawData::TSurfDBEntry* pLcl; INT iFirstSurf = min(pSpanTex->iMaxMipLevel, pSpanTex->cLODTex); LPDIRECTDRAWSURFACE pDDS = pSpanTex->pSurf[iFirstSurf]; INT i; // Init pLcl = (const TPerDDrawData::TSurfDBEntry*)pDDS; pSpanTex->iSizeU = (INT16)pLcl->GetGBLwWidth(); pSpanTex->iSizeV = (INT16)pLcl->GetGBLwHeight(); pSpanTex->uMaskU = (INT16)(pSpanTex->iSizeU - 1); pSpanTex->uMaskV = (INT16)(pSpanTex->iSizeV - 1); pSpanTex->iShiftU = (INT16)IntLog2(pSpanTex->iSizeU); if (0 != pLcl->GetGBLddpfSurface().dwRGBBitCount) { pSpanTex->iShiftPitch[0] = (INT16)IntLog2((UINT32)(pLcl->GetGBLlPitch()* 8)/ pLcl->GetGBLddpfSurface().dwRGBBitCount); } else { pSpanTex->iShiftPitch[0] = (INT16)IntLog2(((UINT32)pLcl->GetGBLwWidth()* 8)); } pSpanTex->iShiftV = (INT16)IntLog2(pSpanTex->iSizeV); pSpanTex->uMaskV = pSpanTex->uMaskV; // Check if the texture size is power of 2 /* if (!ValidTextureSize(pSpanTex->iSizeU, pSpanTex->iShiftU, pSpanTex->iSizeV, pSpanTex->iShiftV)) { return DDERR_INVALIDPARAMS; }*/ // Check for mipmap if any. // iPreSizeU and iPreSizeV store the size(u and v) of the previous level // mipmap. They are init'ed with the first texture size. INT16 iPreSizeU = pSpanTex->iSizeU, iPreSizeV = pSpanTex->iSizeV; for ( i = iFirstSurf + 1; i <= pSpanTex->cLODTex; i++) { pDDS = pSpanTex->pSurf[i]; // Check for invalid mipmap texture size pLcl = (const TPerDDrawData::TSurfDBEntry*)pDDS; /* if (!ValidMipmapSize(iPreSizeU, (INT16)DDSurf_Width(pLcl)) || !ValidMipmapSize(iPreSizeV, (INT16)DDSurf_Height(pLcl))) { return DDERR_INVALIDPARAMS; }*/ if (0 != pLcl->GetGBLddpfSurface().dwRGBBitCount) { pSpanTex->iShiftPitch[i - iFirstSurf] = (INT16)IntLog2(((UINT32)pLcl->GetGBLlPitch()* 8)/ pLcl->GetGBLddpfSurface().dwRGBBitCount); } else { pSpanTex->iShiftPitch[i - iFirstSurf] = (INT16)IntLog2(((UINT32)pLcl->GetGBLwWidth()*8)); } iPreSizeU = (INT16)pLcl->GetGBLwWidth(); iPreSizeV = (INT16)pLcl->GetGBLwHeight(); } pSpanTex->cLOD = pSpanTex->cLODTex - iFirstSurf; pSpanTex->iMaxScaledLOD = ((pSpanTex->cLOD + 1) << LOD_SHIFT) - 1; pSpanTex->uFlags &= ~D3DI_SPANTEX_MAXMIPLEVELS_DIRTY; return DD_OK; } void RastLockSpanTexture(void) { INT i, j; PD3DI_SPANTEX pSpanTex; HRESULT hr; if (IsTextureOff()) return; for( j= 0; j< (INT)m_RastCtx.cActTex; j++) { pSpanTex= m_RastCtx.pTexture[j]; if((pSpanTex->uFlags& D3DI_SPANTEX_MAXMIPLEVELS_DIRTY)!= 0) { hr= SetSizesSpanTexture(pSpanTex); if( hr!= D3D_OK) { RastUnlockSpanTexture(); return; } } INT iFirstSurf = min(pSpanTex->iMaxMipLevel, pSpanTex->cLODTex); for (i = iFirstSurf; i <= pSpanTex->cLODTex; i++) { const TPerDDrawData::TSurfDBEntry* pSurfDBEntry= reinterpret_cast( pSpanTex->pSurf[i]); if((pSurfDBEntry->GetLCLddsCaps().dwCaps& DDSCAPS_VIDEOMEMORY)!= 0) { TSurface* pSurf= GetPerDDrawData().GetDriver().GetSurface( *pSurfDBEntry); pSpanTex->pBits[i-iFirstSurf]= reinterpret_cast( pSurf->Lock( 0, NULL)); } } pSpanTex->uFlags|= D3DI_SPANTEX_SURFACES_LOCKED; } } void UpdateColorKeyAndPalette() { // TODO: Palette INT j; PD3DI_SPANTEX pSpanTex; // Set the transparent bit and the transparent color with pSurf[0] const TPerDDrawData::TSurfDBEntry* pLcl; for (j = 0; j < (INT)m_RastCtx.cActTex; j++) { pSpanTex = m_RastCtx.pTexture[j]; if ((pSpanTex != NULL) && (pSpanTex->pSurf[0] != NULL)) { pLcl= (const TPerDDrawData::TSurfDBEntry*)(pSpanTex->pSurf[0]); // Palette might be changed if (pSpanTex->Format == D3DI_SPTFMT_PALETTE8 || pSpanTex->Format == D3DI_SPTFMT_PALETTE4) { TPalDBEntry* pPalDBEntry= pLcl->GetPalette(); assert( pPalDBEntry!= NULL); if((pPalDBEntry->GetFlags()& DDRAWIPAL_ALPHA)!= 0) pSpanTex->uFlags|= D3DI_SPANTEX_ALPHAPALETTE; pSpanTex->pPalette= reinterpret_cast< PUINT32>( pPalDBEntry->GetEntries()); } // texture does not have a ColorKey value if (pSpanTex->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) { pSpanTex->uFlags &= ~D3DI_SPANTEX_HAS_TRANSPARENT; // TODO: // make sure this state change is recognized, and a new // texture read function is used // StateChanged(RAST_TSS_DIRTYBIT(j, D3DTSS_TEXTUREMAP)); } } } } bool NotCulled(LPD3DTLVERTEX pV0, LPD3DTLVERTEX pV1, LPD3DTLVERTEX pV2) { if (m_RastCtx.pdwRenderState[D3DRS_CULLMODE] == D3DCULL_NONE) return true; FLOAT x1, y1, x2x1, x3x1, y2y1, y3y1, fDet; x1 = pV0->sx; y1 = pV0->sy; x2x1 = pV1->sx - x1; y2y1 = pV1->sy - y1; x3x1 = pV2->sx - x1; y3y1 = pV2->sy - y1; fDet = x2x1 * y3y1 - x3x1 * y2y1; if (0. == fDet) return false; switch ( m_RastCtx.pdwRenderState[D3DRS_CULLMODE] ) { case D3DCULL_CW: if ( fDet > 0.f ) { return false; } break; case D3DCULL_CCW: if ( fDet < 0.f ) { return false; } break; } return true; } void DoDrawOnePrimitive( UINT16 FvfStride, PUINT8 pVtx, D3DPRIMITIVETYPE PrimType, UINT cPrims) { INT i; PUINT8 pV0, pV1, pV2; HRESULT hr; switch (PrimType) { case D3DPT_POINTLIST: { D3DVALUE fPointSize( GetRenderStateDV( D3DRS_POINTSIZE)); DWORD dwPScaleEn( GetRenderStateDW( D3DRS_POINTSCALEENABLE)); if( m_fvfData.offsetPSize!= 0 || fPointSize!= 1.0f || dwPScaleEn!= 0) { DWORD dwOldFill( GetRenderStateDW( D3DRS_FILLMODE)); DWORD dwOldShade( GetRenderStateDW( D3DRS_SHADEMODE)); DWORD dwOldCull( GetRenderStateDW( D3DRS_CULLMODE)); if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID); SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT); SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); Begin(); } m_PrimProc.BeginPrimSet( D3DPT_TRIANGLELIST, m_fvfData.vtxType); D3DHAL_DP2VIEWPORTINFO VInfo; GetDP2ViewportInfo( VInfo); D3DVALUE fPScaleA( GetRenderStateDV( D3DRS_POINTSCALE_A)); D3DVALUE fPScaleB( GetRenderStateDV( D3DRS_POINTSCALE_B)); D3DVALUE fPScaleC( GetRenderStateDV( D3DRS_POINTSCALE_C)); D3DVALUE fPSizeMax( GetRenderStateDV( D3DRS_POINTSIZE_MAX)); D3DVALUE fPSizeMin( GetRenderStateDV( D3DRS_POINTSIZE_MIN)); clamp( fPSizeMax, 0.0f, CRGBDriver::GetCaps().MaxPointSize); clamp( fPSizeMin, 0.0f, fPSizeMax); for (i = (INT)cPrims; i > 0; i--) { if( m_fvfData.offsetPSize!= 0) fPointSize= *reinterpret_cast (pVtx+ m_fvfData.offsetPSize); else fPointSize= GetRenderStateDV( D3DRS_POINTSIZE); if( dwPScaleEn) { D3DVALUE* pXYZ= reinterpret_cast< D3DVALUE*>(pVtx); D3DVALUE De( sqrtf( pXYZ[0]* pXYZ[0]+ pXYZ[1]* pXYZ[1]+ pXYZ[2]* pXYZ[2])); fPointSize*= VInfo.dwHeight* sqrtf( 1.0f/( fPScaleA+ fPScaleB* De+ fPScaleC* De* De)); } clamp( fPointSize, fPSizeMin, fPSizeMax); fPointSize*= 0.5f; RAST_GENERIC_VERTEX GV0, GV1, GV2, GV3; PackGenVertex( pVtx, &GV0); GV3= GV2= GV1= GV0; GV0.sx-= fPointSize; GV0.sy-= fPointSize; GV1.sx+= fPointSize; GV1.sy-= fPointSize; GV2.sx+= fPointSize; GV2.sy+= fPointSize; GV3.sx-= fPointSize; GV3.sy+= fPointSize; if( GetRenderStateDV( D3DRS_POINTSPRITEENABLE)!= 0) { for( INT iT( 0); iT< m_fvfData.cActTex; iT++) { GV0.texCoord[iT].tu= 0.0f; GV0.texCoord[iT].tv= 0.0f; GV1.texCoord[iT].tu= 1.0f; GV1.texCoord[iT].tv= 0.0f; GV2.texCoord[iT].tu= 1.0f; GV2.texCoord[iT].tv= 1.0f; GV3.texCoord[iT].tu= 0.0f; GV3.texCoord[iT].tv= 1.0f; } } m_PrimProc.Tri( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV2)); m_PrimProc.Tri( reinterpret_cast(&GV1), reinterpret_cast(&GV2), reinterpret_cast(&GV3)); pVtx += FvfStride; } if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, dwOldFill); SetRenderState( D3DRS_SHADEMODE, dwOldShade); SetRenderState( D3DRS_CULLMODE, dwOldCull); } } else { for (i = (INT)cPrims; i > 0; i--) { m_PrimProc.Point( reinterpret_cast(pVtx), reinterpret_cast(pVtx)); pVtx += FvfStride; } } } break; case D3DPT_LINELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx; pVtx += FvfStride; pV1 = pVtx; pVtx += FvfStride; m_PrimProc.Line( reinterpret_cast(pV0), reinterpret_cast(pV1), reinterpret_cast(pV0)); } break; case D3DPT_LINESTRIP: { pV1 = pVtx; // Disable last-pixel setting for shared verties and store prestate. UINT uOldFlags= m_PrimProc.GetFlags(); m_PrimProc.ClrFlags(PPF_DRAW_LAST_LINE_PIXEL); // Initial pV0. for (i = (INT)cPrims; i > 1; i--) { pV0 = pV1; pVtx += FvfStride; pV1 = pVtx; m_PrimProc.Line( reinterpret_cast(pV0), reinterpret_cast(pV1), reinterpret_cast(pV0)); } // Restore last-pixel setting. m_PrimProc.SetFlags(uOldFlags& PPF_DRAW_LAST_LINE_PIXEL); // Draw last line with last-pixel setting from state. if (i == 1) { pV0 = pVtx + FvfStride; m_PrimProc.Line( reinterpret_cast(pV1), reinterpret_cast(pV0), reinterpret_cast(pV1)); } } break; case D3DPT_TRIANGLELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx; pVtx += FvfStride; pV1 = pVtx; pVtx += FvfStride; pV2 = pVtx; pVtx += FvfStride; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } break; case D3DPT_TRIANGLESTRIP: { // Get initial vertex values. pV1 = pVtx; pVtx += FvfStride; pV2 = pVtx; pVtx += FvfStride; for (i = (INT)cPrims; i > 1; i -= 2) { pV0 = pV1; pV1 = pV2; pV2 = pVtx; pVtx += FvfStride; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } pV0 = pV1; pV1 = pV2; pV2 = pVtx; pVtx += FvfStride; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV1)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV1); break; } } if (i > 0) { pV0 = pV1; pV1 = pV2; pV2 = pVtx; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } } break; case D3DPT_TRIANGLEFAN: { pV2 = pVtx; pVtx += FvfStride; // Preload initial pV0. pV1 = pVtx; pVtx += FvfStride; for (i = (INT)cPrims; i > 0; i--) { pV0 = pV1; pV1 = pVtx; pVtx += FvfStride; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } } break; default: assert( false); } } void DoDrawOneGenPrimitive( UINT16 FvfStride, PUINT8 pVtx, D3DPRIMITIVETYPE PrimType, UINT cPrims) { INT i; RAST_GENERIC_VERTEX GV0, GV1, GV2; PUINT8 pV0, pV1, pV2; HRESULT hr; switch (PrimType) { case D3DPT_POINTLIST: { D3DVALUE fPointSize( GetRenderStateDV( D3DRS_POINTSIZE)); DWORD dwPScaleEn( GetRenderStateDW( D3DRS_POINTSCALEENABLE)); if( m_fvfData.offsetPSize!= 0 || fPointSize!= 1.0f || dwPScaleEn!= 0) { DWORD dwOldFill( GetRenderStateDW( D3DRS_FILLMODE)); DWORD dwOldShade( GetRenderStateDW( D3DRS_SHADEMODE)); DWORD dwOldCull( GetRenderStateDW( D3DRS_CULLMODE)); if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID); SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT); SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); Begin(); } m_PrimProc.BeginPrimSet( D3DPT_TRIANGLELIST, m_fvfData.vtxType); D3DHAL_DP2VIEWPORTINFO VInfo; GetDP2ViewportInfo( VInfo); D3DVALUE fPScaleA( GetRenderStateDV( D3DRS_POINTSCALE_A)); D3DVALUE fPScaleB( GetRenderStateDV( D3DRS_POINTSCALE_B)); D3DVALUE fPScaleC( GetRenderStateDV( D3DRS_POINTSCALE_C)); D3DVALUE fPSizeMax( GetRenderStateDV( D3DRS_POINTSIZE_MAX)); D3DVALUE fPSizeMin( GetRenderStateDV( D3DRS_POINTSIZE_MIN)); clamp( fPSizeMax, 0.0f, CRGBDriver::GetCaps().MaxPointSize); clamp( fPSizeMin, 0.0f, fPSizeMax); for (i = (INT)cPrims; i > 0; i--) { if( m_fvfData.offsetPSize!= 0) fPointSize= *reinterpret_cast (pVtx+ m_fvfData.offsetPSize); else fPointSize= GetRenderStateDV( D3DRS_POINTSIZE); if( dwPScaleEn) { D3DVALUE* pXYZ= reinterpret_cast< D3DVALUE*>(pVtx); D3DVALUE De( sqrtf( pXYZ[0]* pXYZ[0]+ pXYZ[1]* pXYZ[1]+ pXYZ[2]* pXYZ[2])); fPointSize*= VInfo.dwHeight* sqrtf( 1.0f/( fPScaleA+ fPScaleB* De+ fPScaleC* De* De)); } clamp( fPointSize, fPSizeMin, fPSizeMax); fPointSize*= 0.5f; RAST_GENERIC_VERTEX GV3; PackGenVertex( pVtx, &GV0); GV3= GV2= GV1= GV0; GV0.sx-= fPointSize; GV0.sy-= fPointSize; GV1.sx+= fPointSize; GV1.sy-= fPointSize; GV2.sx+= fPointSize; GV2.sy+= fPointSize; GV3.sx-= fPointSize; GV3.sy+= fPointSize; if( GetRenderStateDV( D3DRS_POINTSPRITEENABLE)!= 0) { for( INT iT( 0); iT< m_fvfData.cActTex; iT++) { GV0.texCoord[iT].tu= 0.0f; GV0.texCoord[iT].tv= 0.0f; GV1.texCoord[iT].tu= 1.0f; GV1.texCoord[iT].tv= 0.0f; GV2.texCoord[iT].tu= 1.0f; GV2.texCoord[iT].tv= 1.0f; GV3.texCoord[iT].tu= 0.0f; GV3.texCoord[iT].tv= 1.0f; } } m_PrimProc.Tri( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV2)); m_PrimProc.Tri( reinterpret_cast(&GV1), reinterpret_cast(&GV2), reinterpret_cast(&GV3)); pVtx += FvfStride; } if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, dwOldFill); SetRenderState( D3DRS_SHADEMODE, dwOldShade); SetRenderState( D3DRS_CULLMODE, dwOldCull); } } else { for (i = (INT)cPrims; i > 0; i--) { PackGenVertex( pVtx, &GV0); m_PrimProc.Point( reinterpret_cast(&GV0), reinterpret_cast(&GV0)); pVtx += FvfStride; } } } break; case D3DPT_LINELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx; pVtx += FvfStride; pV1 = pVtx; pVtx += FvfStride; PackGenVertex( pV0, &GV0); PackGenVertex( pV1, &GV1); m_PrimProc.Line( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV0)); } break; case D3DPT_LINESTRIP: { pV1 = pVtx; PackGenVertex( pV1, &GV1); // Disable last-pixel setting for shared verties and store prestate. UINT uOldFlags= m_PrimProc.GetFlags(); m_PrimProc.ClrFlags(PPF_DRAW_LAST_LINE_PIXEL); // Initial pV0. for (i = (INT)cPrims; i > 1; i--) { pV0 = pV1; GV0= GV1; pVtx += FvfStride; pV1 = pVtx; PackGenVertex( pV1, &GV1); m_PrimProc.Line( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV0)); } // Restore last-pixel setting. m_PrimProc.SetFlags(uOldFlags& PPF_DRAW_LAST_LINE_PIXEL); // Draw last line with last-pixel setting from state. if (i == 1) { pV0 = pVtx + FvfStride; PackGenVertex( pV0, &GV0); m_PrimProc.Line( reinterpret_cast(&GV1), reinterpret_cast(&GV0), reinterpret_cast(&GV1)); } } break; case D3DPT_TRIANGLELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx; pVtx += FvfStride; pV1 = pVtx; pVtx += FvfStride; pV2 = pVtx; pVtx += FvfStride; PackGenVertex( pV0, &GV0); PackGenVertex( pV1, &GV1); PackGenVertex( pV2, &GV2); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } break; case D3DPT_TRIANGLESTRIP: { // Get initial vertex values. pV1 = pVtx; pVtx += FvfStride; pV2 = pVtx; pVtx += FvfStride; PackGenVertex( pV1, &GV1); PackGenVertex( pV2, &GV2); for (i = (INT)cPrims; i > 1; i -= 2) { pV0 = pV1; GV0 = GV1; pV1 = pV2; GV1 = GV2; pV2 = pVtx; PackGenVertex( pV2, &GV2); pVtx += FvfStride; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } pV0 = pV1; GV0 = GV1; pV1 = pV2; GV1 = GV2; pV2 = pVtx; PackGenVertex( pV2, &GV2); pVtx += FvfStride; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV1)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV1); break; } } if (i > 0) { pV0 = pV1; GV0 = GV1; pV1 = pV2; GV1 = GV2; pV2 = pVtx; PackGenVertex( pV2, &GV2); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } } break; case D3DPT_TRIANGLEFAN: { pV2 = pVtx; PackGenVertex( pV2, &GV2); pVtx += FvfStride; // Preload initial pV0. pV1 = pVtx; PackGenVertex( pV1, &GV1); pVtx += FvfStride; for (i = (INT)cPrims; i > 0; i--) { pV0 = pV1; GV0 = GV1; pV1 = pVtx; PackGenVertex( pV1, &GV1); pVtx += FvfStride; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } } break; default: assert( false); } } void DoDrawOneIndexedPrimitive( UINT16 FvfStride, PUINT8 pVtx, LPWORD puIndices, D3DPRIMITIVETYPE PrimType, UINT cPrims) { INT i; PUINT8 pV0, pV1, pV2; HRESULT hr; switch(PrimType) { case D3DPT_POINTLIST: { D3DVALUE fPointSize( GetRenderStateDV( D3DRS_POINTSIZE)); DWORD dwPScaleEn( GetRenderStateDW( D3DRS_POINTSCALEENABLE)); if( m_fvfData.offsetPSize!= 0 || fPointSize!= 1.0f || dwPScaleEn!= 0) { DWORD dwOldFill( GetRenderStateDW( D3DRS_FILLMODE)); DWORD dwOldShade( GetRenderStateDW( D3DRS_SHADEMODE)); DWORD dwOldCull( GetRenderStateDW( D3DRS_CULLMODE)); if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID); SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT); SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); Begin(); } m_PrimProc.BeginPrimSet( D3DPT_TRIANGLELIST, m_fvfData.vtxType); D3DHAL_DP2VIEWPORTINFO VInfo; GetDP2ViewportInfo( VInfo); D3DVALUE fPScaleA( GetRenderStateDV( D3DRS_POINTSCALE_A)); D3DVALUE fPScaleB( GetRenderStateDV( D3DRS_POINTSCALE_B)); D3DVALUE fPScaleC( GetRenderStateDV( D3DRS_POINTSCALE_C)); D3DVALUE fPSizeMax( GetRenderStateDV( D3DRS_POINTSIZE_MAX)); D3DVALUE fPSizeMin( GetRenderStateDV( D3DRS_POINTSIZE_MIN)); clamp( fPSizeMax, 0.0f, CRGBDriver::GetCaps().MaxPointSize); clamp( fPSizeMin, 0.0f, fPSizeMax); for (i = (INT)cPrims; i > 0; i--) { if( m_fvfData.offsetPSize!= 0) fPointSize= *reinterpret_cast (pVtx+ m_fvfData.offsetPSize); else fPointSize= GetRenderStateDV( D3DRS_POINTSIZE); if( dwPScaleEn) { D3DVALUE* pXYZ= reinterpret_cast< D3DVALUE*>(pVtx); D3DVALUE De( sqrtf( pXYZ[0]* pXYZ[0]+ pXYZ[1]* pXYZ[1]+ pXYZ[2]* pXYZ[2])); fPointSize*= VInfo.dwHeight* sqrtf( 1.0f/( fPScaleA+ fPScaleB* De+ fPScaleC* De* De)); } clamp( fPointSize, fPSizeMin, fPSizeMax); fPointSize*= 0.5f; RAST_GENERIC_VERTEX GV0, GV1, GV2, GV3; pV0 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV0, &GV0); GV3= GV2= GV1= GV0; GV0.sx-= fPointSize; GV0.sy-= fPointSize; GV1.sx+= fPointSize; GV1.sy-= fPointSize; GV2.sx+= fPointSize; GV2.sy+= fPointSize; GV3.sx-= fPointSize; GV3.sy+= fPointSize; if( GetRenderStateDV( D3DRS_POINTSPRITEENABLE)!= 0) { for( INT iT( 0); iT< m_fvfData.cActTex; iT++) { GV0.texCoord[iT].tu= 0.0f; GV0.texCoord[iT].tv= 0.0f; GV1.texCoord[iT].tu= 1.0f; GV1.texCoord[iT].tv= 0.0f; GV2.texCoord[iT].tu= 1.0f; GV2.texCoord[iT].tv= 1.0f; GV3.texCoord[iT].tu= 0.0f; GV3.texCoord[iT].tv= 1.0f; } } m_PrimProc.Tri( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV2)); m_PrimProc.Tri( reinterpret_cast(&GV1), reinterpret_cast(&GV2), reinterpret_cast(&GV3)); pVtx += FvfStride; } if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, dwOldFill); SetRenderState( D3DRS_SHADEMODE, dwOldShade); SetRenderState( D3DRS_CULLMODE, dwOldCull); } } else { for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx + FvfStride * (*puIndices++); m_PrimProc.Point( reinterpret_cast(pV0), reinterpret_cast(pV0)); } } } break; case D3DPT_LINELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx + FvfStride * (*puIndices++); pV1 = pVtx + FvfStride * (*puIndices++); m_PrimProc.Line( reinterpret_cast(pV0), reinterpret_cast(pV1), reinterpret_cast(pV0)); } break; case D3DPT_LINESTRIP: { // Disable last-pixel setting for shared verties and store prestate. UINT uOldFlags= m_PrimProc.GetFlags(); m_PrimProc.ClrFlags(PPF_DRAW_LAST_LINE_PIXEL); // Initial pV1. pV1 = pVtx + FvfStride * (*puIndices++); for (i = (INT)cPrims; i > 1; i--) { pV0 = pV1; pV1 = pVtx + FvfStride * (*puIndices++); m_PrimProc.Line( reinterpret_cast(pV0), reinterpret_cast(pV1), reinterpret_cast(pV0)); } // Restore last-pixel setting. m_PrimProc.SetFlags(uOldFlags& PPF_DRAW_LAST_LINE_PIXEL); // Draw last line with last-pixel setting from state. if (i == 1) { pV0 = pVtx + FvfStride * (*puIndices); m_PrimProc.Line( reinterpret_cast(pV1), reinterpret_cast(pV0), reinterpret_cast(pV1)); } } break; case D3DPT_TRIANGLELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx + FvfStride * (*puIndices++); pV1 = pVtx + FvfStride * (*puIndices++); pV2 = pVtx + FvfStride * (*puIndices++); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } break; case D3DPT_TRIANGLESTRIP: { // Get initial vertex values. pV1 = pVtx + FvfStride * (*puIndices++); pV2 = pVtx + FvfStride * (*puIndices++); for (i = (INT)cPrims; i > 1; i-= 2) { pV0 = pV1; pV1 = pV2; pV2 = pVtx + FvfStride * (*puIndices++); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } pV0 = pV1; pV1 = pV2; pV2 = pVtx + FvfStride * (*puIndices++); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV1)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV1); break; } } if (i > 0) { pV0 = pV1; pV1 = pV2; pV2 = pVtx + FvfStride * (*puIndices++); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } } break; case D3DPT_TRIANGLEFAN: { pV2 = pVtx + FvfStride * (*puIndices++); // Preload initial pV0. pV1 = pVtx + FvfStride * (*puIndices++); for (i = (INT)cPrims; i > 0; i--) { pV0 = pV1; pV1 = pVtx + FvfStride * (*puIndices++); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } } break; } } void DoDrawOneGenIndexedPrimitive( UINT16 FvfStride, PUINT8 pVtx, LPWORD puIndices, D3DPRIMITIVETYPE PrimType, UINT cPrims) { INT i; RAST_GENERIC_VERTEX GV0, GV1, GV2; PUINT8 pV0, pV1, pV2; HRESULT hr; switch(PrimType) { case D3DPT_POINTLIST: { D3DVALUE fPointSize( GetRenderStateDV( D3DRS_POINTSIZE)); DWORD dwPScaleEn( GetRenderStateDW( D3DRS_POINTSCALEENABLE)); if( m_fvfData.offsetPSize!= 0 || fPointSize!= 1.0f || dwPScaleEn!= 0) { DWORD dwOldFill( GetRenderStateDW( D3DRS_FILLMODE)); DWORD dwOldShade( GetRenderStateDW( D3DRS_SHADEMODE)); DWORD dwOldCull( GetRenderStateDW( D3DRS_CULLMODE)); if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID); SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT); SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); Begin(); } m_PrimProc.BeginPrimSet( D3DPT_TRIANGLELIST, m_fvfData.vtxType); D3DHAL_DP2VIEWPORTINFO VInfo; GetDP2ViewportInfo( VInfo); D3DVALUE fPScaleA( GetRenderStateDV( D3DRS_POINTSCALE_A)); D3DVALUE fPScaleB( GetRenderStateDV( D3DRS_POINTSCALE_B)); D3DVALUE fPScaleC( GetRenderStateDV( D3DRS_POINTSCALE_C)); D3DVALUE fPSizeMax( GetRenderStateDV( D3DRS_POINTSIZE_MAX)); D3DVALUE fPSizeMin( GetRenderStateDV( D3DRS_POINTSIZE_MIN)); clamp( fPSizeMax, 0.0f, CRGBDriver::GetCaps().MaxPointSize); clamp( fPSizeMin, 0.0f, fPSizeMax); for (i = (INT)cPrims; i > 0; i--) { if( m_fvfData.offsetPSize!= 0) fPointSize= *reinterpret_cast (pVtx+ m_fvfData.offsetPSize); else fPointSize= GetRenderStateDV( D3DRS_POINTSIZE); if( dwPScaleEn) { D3DVALUE* pXYZ= reinterpret_cast< D3DVALUE*>(pVtx); D3DVALUE De( sqrtf( pXYZ[0]* pXYZ[0]+ pXYZ[1]* pXYZ[1]+ pXYZ[2]* pXYZ[2])); fPointSize*= VInfo.dwHeight* sqrtf( 1.0f/( fPScaleA+ fPScaleB* De+ fPScaleC* De* De)); } clamp( fPointSize, fPSizeMin, fPSizeMax); fPointSize*= 0.5f; RAST_GENERIC_VERTEX GV3; pV0 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV0, &GV0); GV3= GV2= GV1= GV0; GV0.sx-= fPointSize; GV0.sy-= fPointSize; GV1.sx+= fPointSize; GV1.sy-= fPointSize; GV2.sx+= fPointSize; GV2.sy+= fPointSize; GV3.sx-= fPointSize; GV3.sy+= fPointSize; if( GetRenderStateDV( D3DRS_POINTSPRITEENABLE)!= 0) { for( INT iT( 0); iT< m_fvfData.cActTex; iT++) { GV0.texCoord[iT].tu= 0.0f; GV0.texCoord[iT].tv= 0.0f; GV1.texCoord[iT].tu= 1.0f; GV1.texCoord[iT].tv= 0.0f; GV2.texCoord[iT].tu= 1.0f; GV2.texCoord[iT].tv= 1.0f; GV3.texCoord[iT].tu= 0.0f; GV3.texCoord[iT].tv= 1.0f; } } m_PrimProc.Tri( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV2)); m_PrimProc.Tri( reinterpret_cast(&GV1), reinterpret_cast(&GV2), reinterpret_cast(&GV3)); pVtx += FvfStride; } if( dwOldFill!= D3DFILL_SOLID || dwOldShade!= D3DSHADE_FLAT || dwOldCull!= D3DCULL_CCW) { End(); SetRenderState( D3DRS_FILLMODE, dwOldFill); SetRenderState( D3DRS_SHADEMODE, dwOldShade); SetRenderState( D3DRS_CULLMODE, dwOldCull); } } else { for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV0, &GV0); m_PrimProc.Point( reinterpret_cast(&GV0), reinterpret_cast(&GV0)); } } } break; case D3DPT_LINELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV0, &GV0); pV1 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV1, &GV1); m_PrimProc.Line( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV0)); } break; case D3DPT_LINESTRIP: { // Disable last-pixel setting for shared verties and store prestate. UINT uOldFlags= m_PrimProc.GetFlags(); m_PrimProc.ClrFlags(PPF_DRAW_LAST_LINE_PIXEL); // Initial pV1. pV1 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV1, &GV1); for (i = (INT)cPrims; i > 1; i--) { pV0 = pV1; GV0 = GV1; pV1 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV1, &GV1); m_PrimProc.Line( reinterpret_cast(&GV0), reinterpret_cast(&GV1), reinterpret_cast(&GV0)); } // Restore last-pixel setting. m_PrimProc.SetFlags(uOldFlags& PPF_DRAW_LAST_LINE_PIXEL); // Draw last line with last-pixel setting from state. if (i == 1) { pV0 = pVtx + FvfStride * (*puIndices); PackGenVertex( pV0, &GV0); m_PrimProc.Line( reinterpret_cast(&GV1), reinterpret_cast(&GV0), reinterpret_cast(&GV1)); } } break; case D3DPT_TRIANGLELIST: for (i = (INT)cPrims; i > 0; i--) { pV0 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV0, &GV0); pV1 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV1, &GV1); pV2 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV2, &GV2); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } break; case D3DPT_TRIANGLESTRIP: { // Get initial vertex values. pV1 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV1, &GV1); pV2 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV2, &GV2); for (i = (INT)cPrims; i > 1; i-= 2) { pV0 = pV1; GV0 = GV1; pV1 = pV2; GV1 = GV2; pV2 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV2, &GV2); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } pV0 = pV1; GV0 = GV1; pV1 = pV2; GV1 = GV2; pV2 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV2, &GV2); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV1)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV1); break; } } if (i > 0) { pV0 = pV1; GV0 = GV1; pV1 = pV2; GV1 = GV2; pV2 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV2, &GV2); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } } break; case D3DPT_TRIANGLEFAN: { pV2 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV2, &GV2); // Preload initial pV0. pV1 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV1, &GV1); for (i = (INT)cPrims; i > 0; i--) { pV0 = pV1; GV0 = GV1; pV1 = pVtx + FvfStride * (*puIndices++); PackGenVertex( pV1, &GV1); // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } } break; } } void DoDrawOneEdgeFlagTriangleFan( UINT16 FvfStride, PUINT8 pVtx, UINT cPrims, UINT32 dwEdgeFlags) { INT i; PUINT8 pV0, pV1, pV2; HRESULT hr; pV2 = pVtx; pVtx += FvfStride; pV0 = pVtx; pVtx += FvfStride; pV1 = pVtx; pVtx += FvfStride; WORD wFlags = 0; if(dwEdgeFlags & 0x2) wFlags |= D3DTRIFLAG_EDGEENABLE1; if(dwEdgeFlags & 0x1) wFlags |= D3DTRIFLAG_EDGEENABLE3; if(cPrims == 1) { if(dwEdgeFlags & 0x4) wFlags |= D3DTRIFLAG_EDGEENABLE2; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { if( wFlags& D3DTRIFLAG_EDGEENABLE1) m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); if( wFlags& D3DTRIFLAG_EDGEENABLE2) m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); if( wFlags& D3DTRIFLAG_EDGEENABLE3) m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } return; } // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { if( wFlags& D3DTRIFLAG_EDGEENABLE1) m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); if( wFlags& D3DTRIFLAG_EDGEENABLE2) m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); if( wFlags& D3DTRIFLAG_EDGEENABLE3) m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } UINT32 dwMask = 0x4; for (i = (INT)cPrims - 2; i > 0; i--) { pV0 = pV1; pV1 = pVtx; pVtx += FvfStride; if(true|| (dwEdgeFlags & dwMask)!= 0) { // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } else { // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } dwMask <<= 1; } pV0 = pV1; pV1 = pVtx; wFlags = 0; if(dwEdgeFlags & dwMask) wFlags |= D3DTRIFLAG_EDGEENABLE1; dwMask <<= 1; if(dwEdgeFlags & dwMask) wFlags |= D3DTRIFLAG_EDGEENABLE2; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); m_PrimProc.Point((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2)) { if( wFlags& D3DTRIFLAG_EDGEENABLE1) m_PrimProc.Line((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV0); if( wFlags& D3DTRIFLAG_EDGEENABLE2) m_PrimProc.Line((LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0); if( wFlags& D3DTRIFLAG_EDGEENABLE3) m_PrimProc.Line((LPD3DTLVERTEX)pV2, (LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)pV0, (LPD3DTLVERTEX)pV1, (LPD3DTLVERTEX)pV2); break; } } void DoDrawOneGenEdgeFlagTriangleFan( UINT16 FvfStride, PUINT8 pVtx, UINT cPrims, UINT32 dwEdgeFlags) { INT i; RAST_GENERIC_VERTEX GV0, GV1, GV2; PUINT8 pV0, pV1, pV2; HRESULT hr; pV2 = pVtx; PackGenVertex( pV2, &GV2); pVtx += FvfStride; pV0 = pVtx; PackGenVertex( pV0, &GV0); pVtx += FvfStride; pV1 = pVtx; PackGenVertex( pV1, &GV1); pVtx += FvfStride; WORD wFlags = 0; if(dwEdgeFlags & 0x2) wFlags |= D3DTRIFLAG_EDGEENABLE1; if(dwEdgeFlags & 0x1) wFlags |= D3DTRIFLAG_EDGEENABLE3; if(cPrims == 1) { if(dwEdgeFlags & 0x4) wFlags |= D3DTRIFLAG_EDGEENABLE2; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { if( wFlags& D3DTRIFLAG_EDGEENABLE1) m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); if( wFlags& D3DTRIFLAG_EDGEENABLE2) m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); if( wFlags& D3DTRIFLAG_EDGEENABLE3) m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } return; } // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { if( wFlags& D3DTRIFLAG_EDGEENABLE1) m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); if( wFlags& D3DTRIFLAG_EDGEENABLE2) m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); if( wFlags& D3DTRIFLAG_EDGEENABLE3) m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } UINT32 dwMask = 0x4; for (i = (INT)cPrims - 2; i > 0; i--) { pV0 = pV1; GV0 = GV1; pV1 = pVtx; PackGenVertex( pV1, &GV1); pVtx += FvfStride; if(true || (dwEdgeFlags & dwMask)!= 0) { // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } else { // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } dwMask <<= 1; } pV0 = pV1; GV0 = GV1; pV1 = pVtx; PackGenVertex( pV1, &GV1); wFlags = 0; if(dwEdgeFlags & dwMask) wFlags |= D3DTRIFLAG_EDGEENABLE1; dwMask <<= 1; if(dwEdgeFlags & dwMask) wFlags |= D3DTRIFLAG_EDGEENABLE2; // TODO: Move into PrimProc. switch (m_RastCtx.pdwRenderState[D3DRS_FILLMODE]) { case D3DFILL_POINT: m_PrimProc.Point((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); m_PrimProc.Point((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); break; case D3DFILL_WIREFRAME: if(NotCulled((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2)) { if( wFlags& D3DTRIFLAG_EDGEENABLE1) m_PrimProc.Line((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV0); if( wFlags& D3DTRIFLAG_EDGEENABLE2) m_PrimProc.Line((LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0); if( wFlags& D3DTRIFLAG_EDGEENABLE3) m_PrimProc.Line((LPD3DTLVERTEX)&GV2, (LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV0); } break; case D3DFILL_SOLID: m_PrimProc.Tri((LPD3DTLVERTEX)&GV0, (LPD3DTLVERTEX)&GV1, (LPD3DTLVERTEX)&GV2); break; } } }; }