Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3259 lines
132 KiB

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<LPDIRECTDRAWSURFACE>(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<LPDIRECTDRAWSURFACE>(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<const D3DHAL_DP2RENDERSTATE*>(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<PUINT32>(
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<const D3DHAL_DP2TEXTURESTAGESTATE*>(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<WORD*>(pIData), pParam->primType,
pParam->PrimitiveCount);
else
DoDrawOneIndexedPrimitive( dwVStride, pVData,
reinterpret_cast<WORD*>(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<WORD*>(pIData), pParam->primType,
pParam->PrimitiveCount);
else
DoDrawOneIndexedPrimitive( dwVStride, pVData,
reinterpret_cast<WORD*>(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<UINT8*>(
reinterpret_cast< TSurface*>(m_RastCtx.pDDS)->Lock( 0, NULL));
if( m_RastCtx.pDDSZ!= NULL)
{
m_RastCtx.pZBits= reinterpret_cast<UINT8*>(
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<TSurface*>(m_RastCtx.pDDS)->Unlock();
if( m_RastCtx.pDDSZ!= NULL)
reinterpret_cast<TSurface*>(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<const TPerDDrawData::TSurfDBEntry*>(
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<const TPerDDrawData::TSurfDBEntry*>(
pSpanTex->pSurf[i]);
if((pSurfDBEntry->GetLCLddsCaps().dwCaps& DDSCAPS_VIDEOMEMORY)!= 0)
{
TSurface* pSurf= GetPerDDrawData().GetDriver().GetSurface( *pSurfDBEntry);
pSpanTex->pBits[i-iFirstSurf]= reinterpret_cast<UINT8*>(
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<D3DVALUE*>
(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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2));
m_PrimProc.Tri(
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(pVtx),
reinterpret_cast<D3DTLVERTEX*>(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<D3DTLVERTEX*>(pV0),
reinterpret_cast<D3DTLVERTEX*>(pV1),
reinterpret_cast<D3DTLVERTEX*>(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<D3DTLVERTEX*>(pV0),
reinterpret_cast<D3DTLVERTEX*>(pV1),
reinterpret_cast<D3DTLVERTEX*>(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<D3DTLVERTEX*>(pV1),
reinterpret_cast<D3DTLVERTEX*>(pV0),
reinterpret_cast<D3DTLVERTEX*>(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<D3DVALUE*>
(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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2));
m_PrimProc.Tri(
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DVALUE*>
(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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2));
m_PrimProc.Tri(
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(pV0),
reinterpret_cast<D3DTLVERTEX*>(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<D3DTLVERTEX*>(pV0),
reinterpret_cast<D3DTLVERTEX*>(pV1),
reinterpret_cast<D3DTLVERTEX*>(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<D3DTLVERTEX*>(pV0),
reinterpret_cast<D3DTLVERTEX*>(pV1),
reinterpret_cast<D3DTLVERTEX*>(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<D3DTLVERTEX*>(pV1),
reinterpret_cast<D3DTLVERTEX*>(pV0),
reinterpret_cast<D3DTLVERTEX*>(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<D3DVALUE*>
(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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2));
m_PrimProc.Tri(
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV2),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&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<D3DTLVERTEX*>(&GV1),
reinterpret_cast<D3DTLVERTEX*>(&GV0),
reinterpret_cast<D3DTLVERTEX*>(&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;
}
}
};
}