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.
 
 
 
 
 
 

3555 lines
112 KiB

/******************************Module*Header**********************************\
*
* *******************
* * D3D SAMPLE CODE *
* *******************
*
* Module Name: d3dprim.c
*
* Content: D3D primitives rendering
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
// For the mipmap LOD calculation
#define BIAS_SHIFT 1
#define CULL_HERE 1
#include <limits.h>
#include "glint.h"
#include "dma.h"
#include "tag.h"
//-----------------------------------------------------------------------------
//
// Specialized hardaware rendering functions for the Permedia3,
// for all primitve types
//
//-----------------------------------------------------------------------------
#define GET_FOG(x) ((x) & 0xff000000 )
#define GET_SPEC(x) ((x) & 0x00ffffff )
#define SEND_R3FVFVERTEX_XYZ(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_VTX | Num; \
MEMORY_BARRIER(); \
dmaPtr[1] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[2] = AS_ULONG(pv[Index]->sy); \
MEMORY_BARRIER(); \
dmaPtr[3] = AS_ULONG(pv[Index]->sz); \
dmaPtr += 4; \
CHECK_FIFO(4); \
}
#define SEND_R3FVFVERTEX_XYZ_STQ(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_STQ_VTX | Num; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[1] = tc[Index].tu1; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[2] = tc[Index].tv1; \
MEMORY_BARRIER(); \
dmaPtr[3] = q[Index]; \
MEMORY_BARRIER(); \
dmaPtr[4] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[5] = AS_ULONG(pv[Index]->sy); \
MEMORY_BARRIER(); \
dmaPtr[6] = AS_ULONG(pv[Index]->sz); \
dmaPtr += 7; \
CHECK_FIFO(7); \
}
#define SEND_R3FVFVERTEX_XYZ_FOG(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_VTX | VTX_SPECULAR | Num; \
MEMORY_BARRIER(); \
dmaPtr[1] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[2] = AS_ULONG(pv[Index]->sy); \
MEMORY_BARRIER(); \
dmaPtr[3] = AS_ULONG(pv[Index]->sz); \
MEMORY_BARRIER(); \
dmaPtr[4] = GET_FOG( FVFSPEC(pv[Index])->specular ); \
dmaPtr += 5; \
CHECK_FIFO(5); \
}
#define SEND_R3FVFVERTEX_XYZ_STQ_FOG(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_STQ_VTX | VTX_SPECULAR | Num; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[1] = tc[Index].tu1; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[2] = tc[Index].tv1; \
MEMORY_BARRIER(); \
dmaPtr[3] = q[Index]; \
MEMORY_BARRIER(); \
dmaPtr[4] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[5] = AS_ULONG(pv[Index]->sy); \
MEMORY_BARRIER(); \
dmaPtr[6] = AS_ULONG(pv[Index]->sz); \
MEMORY_BARRIER(); \
dmaPtr[7] = GET_FOG( FVFSPEC(pv[Index])->specular ); \
dmaPtr += 8; \
CHECK_FIFO(8); \
}
#define SEND_R3FVFVERTEX_XYZ_RGBA(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_VTX | VTX_COLOR | Num; \
MEMORY_BARRIER(); \
dmaPtr[1] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[2] = AS_ULONG(pv[Index]->sy); \
MEMORY_BARRIER(); \
dmaPtr[3] = AS_ULONG(pv[Index]->sz); \
MEMORY_BARRIER(); \
dmaPtr[4] = FVFCOLOR(pv[Index])->color; \
MEMORY_BARRIER(); \
dmaPtr += 5; \
CHECK_FIFO(5); \
}
#define SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_VTX | VTX_COLOR | VTX_SPECULAR | Num; \
MEMORY_BARRIER(); \
dmaPtr[1] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[2] = AS_ULONG(pv[Index]->sy); \
MEMORY_BARRIER(); \
dmaPtr[3] = AS_ULONG(pv[Index]->sz); \
MEMORY_BARRIER(); \
dmaPtr[4] = FVFCOLOR(pv[Index])->color; \
MEMORY_BARRIER(); \
dmaPtr[5] = FVFSPEC(pv[Index])->specular; \
dmaPtr += 6; \
CHECK_FIFO(6); \
}
#define SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_STQ_VTX | VTX_COLOR | VTX_SPECULAR | Num; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[1] = tc[Index].tu1; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[2] = tc[Index].tv1; \
MEMORY_BARRIER(); \
dmaPtr[3] = q[Index]; \
MEMORY_BARRIER(); \
dmaPtr[4] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[5] = AS_ULONG(pv[Index]->sy); \
MEMORY_BARRIER(); \
dmaPtr[6] = AS_ULONG(pv[Index]->sz); \
MEMORY_BARRIER(); \
dmaPtr[7] = FVFCOLOR(pv[Index])->color; \
MEMORY_BARRIER(); \
dmaPtr[8] = FVFSPEC(pv[Index])->specular; \
dmaPtr += 9; \
CHECK_FIFO(9); \
}
#define SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG_POINT(Num, Index, offset) \
{ \
float TempY = Y_ADJUST(pv[Index]->sy); \
if (offset == TRUE) TempY += 1.0f; \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_XYZ_STQ_VTX | VTX_COLOR | VTX_SPECULAR | Num; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[1] = tc[Index].tu1; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[2] = tc[Index].tv1; \
MEMORY_BARRIER(); \
dmaPtr[3] = q[Index]; \
MEMORY_BARRIER(); \
dmaPtr[4] = AS_ULONG(pv[Index]->sx); \
MEMORY_BARRIER(); \
dmaPtr[5] = AS_ULONG(TempY); \
MEMORY_BARRIER(); \
dmaPtr[6] = AS_ULONG(pv[Index]->sz); \
MEMORY_BARRIER(); \
dmaPtr[7] = FVFCOLOR(pv[Index])->color; \
MEMORY_BARRIER(); \
dmaPtr[8] = FVFSPEC(pv[Index])->specular; \
dmaPtr += 9; \
CHECK_FIFO(9); \
}
#define SEND_R3FVFVERTEX_STQ2(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_STQ_VTX | Num; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[1] = tc[Index].tu2; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[2] = tc[Index].tv2; \
MEMORY_BARRIER(); \
dmaPtr[3] = q[Index]; \
dmaPtr += 4; \
CHECK_FIFO(4); \
}
#if DX8_3DTEXTURES
#define SEND_R3FVFVERTEX_3DTEX(Num, Index) \
{ \
MEMORY_BARRIER(); \
dmaPtr[0] = GAMBIT_STQ_VTX | Num; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[1] = tc[Index].tw1; \
MEMORY_BARRIER(); \
*(float volatile*)&dmaPtr[2] = 0; /* Not used */ \
MEMORY_BARRIER(); \
dmaPtr[3] = q[Index]; \
dmaPtr += 4; \
CHECK_FIFO(4); \
}
#endif // DX8_3DTEXTURES
#if DX8_3DTEXTURES
#define GET_TC_3DTEX( Index ) \
*(DWORD *)&tc[Index].tu1 = *(DWORD *)&FVFTEX(pv[Index], 0)->tu; \
*(DWORD *)&tc[Index].tv1 = *(DWORD *)&FVFTEX(pv[Index], 0)->tv; \
*(DWORD *)&tc[Index].tw1 = *(DWORD *)&FVFTEX(pv[Index], 0)->tw;
#endif // DX8_3DTEXTURES
#define GET_TC( Index ) \
*(DWORD *)&tc[Index].tu1 = *(DWORD *)&FVFTEX(pv[Index], 0)->tu; \
*(DWORD *)&tc[Index].tv1 = *(DWORD *)&FVFTEX(pv[Index], 0)->tv;
#if DX8_3DTEXTURES
#define GET_TC2_3DTEX( Index ) \
*(DWORD *)&tc[Index].tu2 = *(DWORD *)&FVFTEX(pv[Index], 1)->tu; \
*(DWORD *)&tc[Index].tv2 = *(DWORD *)&FVFTEX(pv[Index], 1)->tv; \
*(DWORD *)&tc[Index].tw2 = *(DWORD *)&FVFTEX(pv[Index], 1)->tw;
#endif // DX8_3DTEXTURES
#define GET_TC2( Index ) \
*(DWORD *)&tc[Index].tu2 = *(DWORD *)&FVFTEX(pv[Index], 1)->tu; \
*(DWORD *)&tc[Index].tv2 = *(DWORD *)&FVFTEX(pv[Index], 1)->tv;
#define GET_ONE_TEXCOORD(vtx) \
GET_TC(vtx); \
if( pContext->iTexStage[1] != -1 ) \
{ \
GET_TC2(vtx); \
}
#define GET_TEXCOORDS() \
GET_TC(0); GET_TC(1); GET_TC(2); \
if( pContext->iTexStage[1] != -1 ) \
{ \
GET_TC2(0); GET_TC2(1); GET_TC2(2); \
}
#if DX8_3DTEXTURES
#define SCALE_BY_Q_3DTEX( Index ) \
tc[Index].tu1 *= *(float *)&q[Index]; \
tc[Index].tv1 *= *(float *)&q[Index]; \
tc[Index].tw1 *= *(float *)&q[Index];
#endif // DX8_3DTEXTURES
#define SCALE_BY_Q( Index ) \
tc[Index].tu1 *= *(float *)&q[Index]; \
tc[Index].tv1 *= *(float *)&q[Index];
#if DX8_3DTEXTURES
#define SCALE_BY_Q2_3DTEX( Index ) \
tc[Index].tu2 *= *(float *)&q[Index]; \
tc[Index].tv2 *= *(float *)&q[Index]; \
tc[Index].tw2 *= *(float *)&q[Index];
#endif // DX8_3DTEXTURES
#define SCALE_BY_Q2( Index ) \
tc[Index].tu2 *= *(float *)&q[Index]; \
tc[Index].tv2 *= *(float *)&q[Index];
#define DRAW_LINE() \
MEMORY_BARRIER(); \
dmaPtr[0] = DrawLine01_Tag; \
MEMORY_BARRIER(); \
dmaPtr[1] = renderCmd; \
dmaPtr += 2; \
CHECK_FIFO(2)
#define DRAW_POINT() \
MEMORY_BARRIER(); \
dmaPtr[0] = DrawPoint_Tag; \
MEMORY_BARRIER(); \
dmaPtr[1] = renderCmd; \
dmaPtr += 2; \
CHECK_FIFO(2)
#define DRAW_LINE_01_OR_10( vtx ) \
MEMORY_BARRIER(); \
dmaPtr[0] = vtx ? DrawLine01_Tag \
: DrawLine10_Tag; \
MEMORY_BARRIER(); \
dmaPtr[1] = renderCmd; \
dmaPtr += 2; \
CHECK_FIFO(2)
#define DRAW_TRIANGLE() \
MEMORY_BARRIER(); \
dmaPtr[0] = DrawTriangle_Tag; \
MEMORY_BARRIER(); \
dmaPtr[1] = renderCmd; \
dmaPtr += 2; \
CHECK_FIFO(2)
//-----------------------------------------------------------------------------
// Easy edge flag renaming
//-----------------------------------------------------------------------------
#define SIDE_0 D3DTRIFLAG_EDGEENABLE1
#define SIDE_1 D3DTRIFLAG_EDGEENABLE2
#define SIDE_2 D3DTRIFLAG_EDGEENABLE3
#define ALL_SIDES ( SIDE_0 | SIDE_1 | SIDE_2 )
//-----------------------------------------------------------------------------
// Cycle vertex indices for triangle strips viz. 0 -> 1, 1 -> 2, 2 -> 0
// See Graphics Gems 3, Pg 69.
//-----------------------------------------------------------------------------
#define INIT_VERTEX_INDICES(pContext, vtx_a, vtx_b) \
vtx_a = 0; \
vtx_b = 0 ^ 1; \
pContext->dwProvokingVertex = 1;
#define CONST_c (0 ^ 1 ^ 2)
#define CYCLE_VERTEX_INDICES(pContext, vtx_a, vtx_b) \
vtx_a ^= vtx_b; \
vtx_b ^= CONST_c; \
pContext->dwProvokingVertex = vtx_b; \
vtx_b ^= vtx_a;
//-----------------------------------------------------------------------------
// Local typedef for temporary texture coordinate storage
//-----------------------------------------------------------------------------
typedef struct
{
float tu1;
float tv1;
#if DX8_3DTEXTURES
float tw1;
#endif // DX8_3DTEXTURES
float tu2;
float tv2;
#if DX8_3DTEXTURES
float tw2;
#endif // DX8_3DTEXTURES
} TEXCOORDS;
//-----------------------------------------------------------------------------
// Macros to access and validate command and vertex buffer data
// These checks need ALWAYS to be made for all builds, free and checked.
//-----------------------------------------------------------------------------
#define LP_FVF_VERTEX(lpBaseAddr, wIndex) \
(LPD3DTLVERTEX)((LPBYTE)(lpBaseAddr) + (wIndex) * pContext->FVFData.dwStride)
#define LP_FVF_NXT_VTX(lpVtx) \
(LPD3DTLVERTEX)((LPBYTE)(lpVtx) + pContext->FVFData.dwStride)
#define CHECK_DATABUF_LIMITS(pbError, dwVBLen, iIndex ) \
{ \
if (! (((LONG)(iIndex) >= 0) && \
((LONG)(iIndex) <(LONG)dwVBLen))) \
{ \
DISPDBG((ERRLVL,"D3D: Trying to read past Vertex Buffer limits " \
"%d limit= %d ",(LONG)(iIndex), (LONG)dwVBLen)); \
*pbError = TRUE; \
return; \
} \
}
//-----------------------------------------------------------------------------
// Define values for FVF defaults
//-----------------------------------------------------------------------------
const FVFCOLOR gc_FVFColorDefault = { 0xFFFFFFFF };
const FVFSPECULAR gc_FVFSpecDefault = { 0x00000000 };
const FVFTEXCOORDS gc_FVFTexCoordDefault = { 0.0f,
0.0f
#if DX8_3DTEXTURES
, 0.0f
#endif
};
//-----------------------------------------------------------------------------
// Macros and functions for texture coord adjustment on wrapping
//-----------------------------------------------------------------------------
#define SHIFT_SET_0 1
#define SHIFT_SET_1 2
#define TEXSHIFT 1
#if TEXSHIFT
#if 0
// 8.0f as a DWORD
#define TEX_SHIFT_LIMIT 0x41000000
#define FP_SIGN_MASK 0x7fffffff
#define TEXTURE_SHIFT( coord ) \
if(( *(DWORD *)&tc[0].##coord & FP_SIGN_MASK ) > TEX_SHIFT_LIMIT ) \
{ \
myFtoi( &intVal, tc[0].##coord ); \
\
intVal &= ~1; \
\
tc[0].##coord -= intVal; \
tc[1].##coord -= intVal; \
tc[2].##coord -= intVal; \
\
FLUSH_DUE_TO_WRAP( coord, TRUE ); \
}
#endif
#define TEX_SHIFT_LIMIT 4.0
#define TEXTURE_SHIFT( coord ) \
if((tc[0].##coord > TEX_SHIFT_LIMIT ) || \
(tc[0].##coord < -TEX_SHIFT_LIMIT ) ) \
{ \
myFtoi( &intVal, tc[0].##coord ); \
\
intVal &= ~1; \
\
tc[0].##coord -= intVal; \
tc[1].##coord -= intVal; \
tc[2].##coord -= intVal; \
\
FLUSH_DUE_TO_WRAP( coord, TRUE ); \
}
#define WRAP_R3(par, wrapit, vertexSharing) if(wrapit) { \
float elp; \
float erp; \
float emp; \
elp=(float)myFabs(tc[1].##par-tc[0].##par); \
erp=(float)myFabs(tc[2].##par-tc[1].##par); \
emp=(float)myFabs(tc[0].##par-tc[2].##par); \
if( (elp > 0.5f) && (erp > 0.5f) ) \
{ \
if (tc[1].##par < tc[2].##par) { tc[1].##par += 1.0f; } \
else { tc[2].##par += 1.0f; tc[0].##par += 1.0f; } \
FLUSH_DUE_TO_WRAP(par,vertexSharing); \
} \
else if( (erp > 0.5f) && (emp > 0.5f) ) \
{ \
if (tc[2].##par < tc[0].##par) { tc[2].##par += 1.0f; } \
else { tc[0].##par += 1.0f; tc[1].##par += 1.0f; } \
FLUSH_DUE_TO_WRAP(par,vertexSharing); \
} \
else if( (emp > 0.5f) && (elp > 0.5f) ) \
{ \
if(tc[0].##par < tc[1].##par) { tc[0].##par += 1.0f; } \
else { tc[1].##par += 1.0f; tc[2].##par += 1.0f; } \
FLUSH_DUE_TO_WRAP(par,vertexSharing); \
} \
else \
{ \
DONT_FLUSH_DUE_TO_WRAP(par,vertexSharing); \
} \
} else { \
DONT_FLUSH_DUE_TO_WRAP(par,vertexSharing); \
}
//-----------------------------------------------------------------------------
//
// __TextureShift
//
//-----------------------------------------------------------------------------
void
__TextureShift(
P3_D3DCONTEXT *pContext,
TEXCOORDS tc[],
DWORD shiftMask )
{
int intVal;
if( shiftMask & SHIFT_SET_0 )
{
if( pContext->TextureStageState[0].m_dwVal[D3DTSS_ADDRESSU] !=
D3DTADDRESS_CLAMP )
{
TEXTURE_SHIFT( tu1 );
}
if( pContext->TextureStageState[0].m_dwVal[D3DTSS_ADDRESSV] !=
D3DTADDRESS_CLAMP )
{
TEXTURE_SHIFT( tv1 );
}
}
if( shiftMask & SHIFT_SET_1 )
{
if( pContext->TextureStageState[1].m_dwVal[D3DTSS_ADDRESSU] !=
D3DTADDRESS_CLAMP )
{
TEXTURE_SHIFT( tu2 );
}
if( pContext->TextureStageState[1].m_dwVal[D3DTSS_ADDRESSV] !=
D3DTADDRESS_CLAMP )
{
TEXTURE_SHIFT( tv2 );
}
}
} // __TextureShift
#endif //TEXSHIFT
//-----------------------------------------------------------------------------
//
// __BackfaceCullNoTexture
//
//-----------------------------------------------------------------------------
int _inline
__BackfaceCullNoTexture(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[] )
{
DWORD Flags = pContext->Flags;
float PixelArea;
PixelArea = (((pv[0]->sx - pv[2]->sx) * (pv[1]->sy - pv[2]->sy)) -
((pv[1]->sx - pv[2]->sx) * (pv[0]->sy - pv[2]->sy)));
if (CULLED(pContext,PixelArea))
{
return 1;
}
pContext->R3flushDueToTexCoordAdjust = 0;
return 0;
} // __BackfaceCullNoTexture
//-----------------------------------------------------------------------------
//
// __BackfaceCullSingleTex
//
//-----------------------------------------------------------------------------
int _inline
__BackfaceCullSingleTex(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
TEXCOORDS tc[] )
{
DWORD Flags = pContext->Flags;
float PixelArea;
PixelArea = (((pv[0]->sx - pv[2]->sx) * (pv[1]->sy - pv[2]->sy)) -
((pv[1]->sx - pv[2]->sx) * (pv[0]->sy - pv[2]->sy)));
if (CULLED(pContext,PixelArea))
{
return 1;
}
pContext->R3flushDueToTexCoordAdjust = 0;
#if TEXSHIFT
__TextureShift( pContext, tc, SHIFT_SET_0 );
#endif
return 0;
} // __BackfaceCullSingleTex
//-----------------------------------------------------------------------------
//
// __BackfaceCullAndMipMap
//
//-----------------------------------------------------------------------------
int _inline
__BackfaceCullAndMipMap(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
TEXCOORDS tc[] )
{
DWORD Flags = pContext->Flags;
float PixelArea;
int iNewMipLevel;
P3_SURF_INTERNAL* pTexture;
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
P3_DMA_DEFS();
PixelArea = (((pv[0]->sx - pv[2]->sx) * (pv[1]->sy - pv[2]->sy)) -
((pv[1]->sx - pv[2]->sx) * (pv[0]->sy - pv[2]->sy)));
if (CULLED(pContext,PixelArea))
{
return 1;
}
// 39 for vertex data, 2 for triangle and 4 for possible LOD change
// for the three vertex case - the one vertex case will check for
// too much but this shouldn't be a problem.
P3_DMA_GET_BUFFER_ENTRIES( 4 );
pContext->R3flushDueToTexCoordAdjust = 0;
if( Flags & SURFACE_TEXTURING )
{
float TextureArea, textureAreaFactor;
int maxLevel;
pTexture = pContext->pCurrentTexture[TEXSTAGE_0];
// Setup LOD of texture # 0 (if necessary)
if( pContext->bTex0Valid &&
( pContext->TextureStageState[TEXSTAGE_0].m_dwVal[D3DTSS_MIPFILTER] != D3DTFP_NONE )
&& pTexture->bMipMap )
{
maxLevel = pTexture->iMipLevels - 1;
textureAreaFactor = pTexture->fArea * pContext->MipMapLODBias[TEXSTAGE_0];
TextureArea = (((tc[0].tu1 - tc[2].tu1) * (tc[1].tv1 - tc[2].tv1)) -
((tc[1].tu1 - tc[2].tu1) * (tc[0].tv1 - tc[2].tv1))) * textureAreaFactor;
// Ensure that both of these values are positive from now on.
*(signed long *)&PixelArea &= ~(1 << 31);
*(signed long *)&TextureArea &= ~(1 << 31);
FIND_PERMEDIA_MIPLEVEL();
DISPDBG((DBGLVL,"iNewMipLevel = %x",iNewMipLevel));
SEND_P3_DATA( LOD, iNewMipLevel << 8 );
}
pTexture = pContext->pCurrentTexture[TEXSTAGE_1];
// Setup LOD of texture # 1 (if necessary)
if( pContext->bTex1Valid && ( pContext->TextureStageState[TEXSTAGE_1].m_dwVal[D3DTSS_MIPFILTER] != D3DTFP_NONE )
&& pTexture->bMipMap )
{
ASSERTDD( pContext->bTex0Valid, "Second texture valid when first isn't" );
maxLevel = pTexture->iMipLevels - 1;
textureAreaFactor = pTexture->fArea * pContext->MipMapLODBias[TEXSTAGE_1];
TextureArea = (((tc[0].tu2 - tc[2].tu2) * (tc[1].tv2 - tc[2].tv2)) -
((tc[1].tu2 - tc[2].tu2) * (tc[0].tv2 - tc[2].tv2))) * textureAreaFactor;
// Ensure that both of these values are positive from now on.
*(signed long *)&PixelArea &= ~(1 << 31);
*(signed long *)&TextureArea &= ~(1 << 31);
FIND_PERMEDIA_MIPLEVEL();
SEND_P3_DATA( LOD1, iNewMipLevel << 8 );
}
if( pContext->RenderStates[D3DRENDERSTATE_WRAP0] )
{
WRAP_R3( tu1, pContext->RenderStates[D3DRENDERSTATE_WRAP0] & D3DWRAP_U, TRUE );
WRAP_R3( tv1, pContext->RenderStates[D3DRENDERSTATE_WRAP0] & D3DWRAP_V, TRUE );
}
else
{
#if TEXSHIFT
__TextureShift( pContext, tc, SHIFT_SET_0 );
#endif
}
if( pContext->RenderStates[D3DRENDERSTATE_WRAP1] )
{
WRAP_R3( tu2, pContext->RenderStates[D3DRENDERSTATE_WRAP1] & D3DWRAP_U, TRUE );
WRAP_R3( tv2, pContext->RenderStates[D3DRENDERSTATE_WRAP1] & D3DWRAP_V, TRUE );
}
else
{
#if TEXSHIFT
__TextureShift( pContext, tc, SHIFT_SET_1 );
#endif
}
}
P3_DMA_COMMIT_BUFFER();
return 0;
} // __BackfaceCullAndMipMap
//-----------------------------------------------------------------------------
//
// __ProcessTri_1Vtx_NoTexture
//
//-----------------------------------------------------------------------------
int
__ProcessTri_1Vtx_NoTexture(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int vtx )
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
ULONG renderCmd = pContext->RenderCommand;
P3_DMA_DEFS();
#if CULL_HERE
if( __BackfaceCullNoTexture( pContext, pv ))
return 1;
#endif
P3_DMA_GET_BUFFER_ENTRIES( 9 );
if( pContext->Flags & SURFACE_GOURAUD )
{
// 9 DWORDS.
SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(V0FloatS_Tag + (vtx*16), vtx);
}
else
{
DWORD Col0 = FVFCOLOR(pContext->pProvokingVertex)->color;
if( Flags & SURFACE_SPECULAR )
{
DWORD Spec0 = GET_SPEC( FVFSPEC(pContext->pProvokingVertex)->specular );
CLAMP8888( Col0, Col0, Spec0 );
}
if( Flags & SURFACE_FOGENABLE )
{
// 8 DWORDS.
SEND_R3FVFVERTEX_XYZ_FOG(V0FloatS_Tag + (vtx*16), vtx);
}
else
{
// 7 DWORDS.
SEND_R3FVFVERTEX_XYZ(V0FloatS_Tag + (vtx*16), vtx);
}
// 2 DWORDS.
SEND_P3_DATA(ConstantColor, RGBA_MAKE(RGBA_GETBLUE(Col0),
RGBA_GETGREEN(Col0),
RGBA_GETRED(Col0),
RGBA_GETALPHA(Col0)));
}
RENDER_TRAPEZOID(renderCmd);
DRAW_TRIANGLE();
P3_DMA_COMMIT_BUFFER();
return 0;
} // __ProcessTri_1Vtx_NoTexture
//-----------------------------------------------------------------------------
//
// __ProcessTri_3Vtx_NoTexture
//
//-----------------------------------------------------------------------------
int
__ProcessTri_3Vtx_NoTexture(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int WireEdgeFlags)
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
ULONG renderCmd = pContext->RenderCommand;
P3_DMA_DEFS();
#if CULL_HERE
if( __BackfaceCullNoTexture( pContext, pv ))
return 1;
#endif
P3_DMA_GET_BUFFER_ENTRIES( 20 );
if( pContext->Flags & SURFACE_GOURAUD )
{
SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(V2FloatS_Tag, 2);
}
else
{
DWORD Col0 = FVFCOLOR(pContext->pProvokingVertex)->color;
if( Flags & SURFACE_SPECULAR )
{
DWORD Spec0 = GET_SPEC( FVFSPEC(pContext->pProvokingVertex)->specular );
CLAMP8888( Col0, Col0, Spec0 );
}
if( Flags & SURFACE_FOGENABLE )
{
SEND_R3FVFVERTEX_XYZ_FOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_FOG(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ_FOG(V2FloatS_Tag, 2);
}
else
{
SEND_R3FVFVERTEX_XYZ(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ(V2FloatS_Tag, 2);
}
SEND_P3_DATA(ConstantColor, RGBA_MAKE(RGBA_GETBLUE(Col0),
RGBA_GETGREEN(Col0),
RGBA_GETRED(Col0),
RGBA_GETALPHA(Col0)));
}
RENDER_TRAPEZOID(renderCmd);
DRAW_TRIANGLE();
P3_DMA_COMMIT_BUFFER();
return 0;
} // __ProcessTri_3Vtx_NoTexture
//-----------------------------------------------------------------------------
//
// __ProcessTri_1Vtx_PerspSingleTexGouraud
//
//-----------------------------------------------------------------------------
int
__ProcessTri_1Vtx_PerspSingleTexGouraud(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int vtx )
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
TEXCOORDS tc[3];
DWORD q[3];
ULONG renderCmd = pContext->RenderCommand;
#if DX8_3DTEXTURES
P3_SURF_INTERNAL* pTexture = pContext->pCurrentTexture[TEXSTAGE_0];
BOOL b3DTexture = (pTexture ? pTexture->b3DTexture : FALSE);
#endif // DX8_3DTEXTURES
P3_DMA_DEFS();
// We need to refresh all texture coords as they will have been modified
// by the scale by Q and potentially D3D wrapping or TextureShift.
#if DX8_3DTEXTURES
if (b3DTexture)
{
GET_TC_3DTEX(0); GET_TC_3DTEX(1); GET_TC_3DTEX(2);
}
else
{
GET_TC(0); GET_TC(1); GET_TC(2);
}
#else
GET_TC(0); GET_TC(1); GET_TC(2);
#endif // DX8_3DTEXTURES
#if CULL_HERE
if( __BackfaceCullSingleTex( pContext, pv, tc ))
return 1;
#endif
P3_DMA_GET_BUFFER_ENTRIES( 15 );
q[vtx] = *(DWORD *)&(pv[vtx]->rhw);
#if DX8_3DTEXTURES
if (b3DTexture)
{
SCALE_BY_Q_3DTEX( vtx );
}
else
{
SCALE_BY_Q( vtx );
}
#else
SCALE_BY_Q( vtx );
#endif // DX8_3DTEXTURES
#if DX8_3DTEXTURES
if (b3DTexture)
{
SEND_R3FVFVERTEX_3DTEX(V0FloatS1_Tag + (vtx*16), vtx);
}
#endif // DX8_3DTEXTURES
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V0FloatS_Tag + (vtx*16), vtx);
RENDER_TRAPEZOID(renderCmd);
DRAW_TRIANGLE();
P3_DMA_COMMIT_BUFFER();
return pContext->R3flushDueToTexCoordAdjust;
} // __ProcessTri_1Vtx_PerspSingleTexGouraud
//-----------------------------------------------------------------------------
//
// __ProcessTri_3Vtx_PerspSingleTexGouraud
//
//-----------------------------------------------------------------------------
int
__ProcessTri_3Vtx_PerspSingleTexGouraud(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int WireEdgeFlags )
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
TEXCOORDS tc[3];
DWORD q[3];
int forcedQ = 0;
ULONG renderCmd = pContext->RenderCommand;
#if DX8_3DTEXTURES
P3_SURF_INTERNAL* pTexture = pContext->pCurrentTexture[TEXSTAGE_0];
BOOL b3DTexture = (pTexture ? pTexture->b3DTexture : FALSE);
#endif // DX8_3DTEXTURES
P3_DMA_DEFS();
#if DX8_3DTEXTURES
if (b3DTexture)
{
GET_TC_3DTEX(0); GET_TC_3DTEX(1); GET_TC_3DTEX(2);
}
else
{
GET_TC(0); GET_TC(1); GET_TC(2);
}
#else
GET_TC(0); GET_TC(1); GET_TC(2);
#endif // DX8_3DTEXTURES
#if CULL_HERE
if( __BackfaceCullSingleTex( pContext, pv, tc ))
return 1;
#endif
P3_DMA_GET_BUFFER_ENTRIES( 26 );
q[0] = *(DWORD *)&(pv[0]->rhw);
q[1] = *(DWORD *)&(pv[1]->rhw);
q[2] = *(DWORD *)&(pv[2]->rhw);
// Check for equal Q's
if((( q[0] ^ q[1] ) | ( q[1] ^ q[2] )) == 0 )
{
// Force to 1.0f
forcedQ = q[0] = q[1] = q[2] = 0x3f800000;
}
else
{
#if DX8_3DTEXTURES
if (b3DTexture)
{
SCALE_BY_Q_3DTEX( 0 );
SCALE_BY_Q_3DTEX( 1 );
SCALE_BY_Q_3DTEX( 2 );
}
else
{
SCALE_BY_Q( 0 );
SCALE_BY_Q( 1 );
SCALE_BY_Q( 2 );
}
#else
SCALE_BY_Q( 0 );
SCALE_BY_Q( 1 );
SCALE_BY_Q( 2 );
#endif // DX8_3DTEXTURES
}
#if DX8_3DTEXTURES
if (b3DTexture)
{
SEND_R3FVFVERTEX_3DTEX(V0FloatS1_Tag, 0);
}
#endif // DX8_3DTEXTURES
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V0FloatS_Tag, 0);
#if DX8_3DTEXTURES
if (b3DTexture)
{
SEND_R3FVFVERTEX_3DTEX(V1FloatS1_Tag, 1);
}
#endif // DX8_3DTEXTURES
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V1FloatS_Tag, 1);
P3_DMA_COMMIT_BUFFER();
P3_DMA_GET_BUFFER_ENTRIES( 15 );
#if DX8_3DTEXTURES
if (b3DTexture)
{
SEND_R3FVFVERTEX_3DTEX(V2FloatS1_Tag, 2);
}
#endif // DX8_3DTEXTURES
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V2FloatS_Tag, 2);
RENDER_TRAPEZOID(renderCmd);
DRAW_TRIANGLE();
P3_DMA_COMMIT_BUFFER();
return ( pContext->R3flushDueToTexCoordAdjust | forcedQ );
} // __ProcessTri_3Vtx_PerspSingleTexGouraud
//-----------------------------------------------------------------------------
//
// __ProcessTri_1Vtx_Generic
//
//-----------------------------------------------------------------------------
int
__ProcessTri_1Vtx_Generic(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int vtx )
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
TEXCOORDS tc[3];
DWORD q[3];
ULONG renderCmd = pContext->RenderCommand;
P3_DMA_DEFS();
// We need to refresh all texture coords as they will have been modified
// by the scale by Q and potentially D3D wrapping or TextureShift.
GET_TEXCOORDS();
if( __BackfaceCullAndMipMap( pContext, pv, tc ))
return 1;
if( Flags & SURFACE_PERSPCORRECT )
{
q[vtx] = *(DWORD *)&(pv[vtx]->rhw);
SCALE_BY_Q( vtx );
}
// Send vertex data including check for flat shading
P3_DMA_GET_BUFFER_ENTRIES( 16 );
if( pContext->Flags & SURFACE_GOURAUD )
{
// 9 DWORDS.
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V0FloatS_Tag + (vtx*16), vtx);
}
else
{
DWORD Col0 = FVFCOLOR(pContext->pProvokingVertex)->color;
if( Flags & SURFACE_SPECULAR )
{
DWORD Spec0 = GET_SPEC( FVFSPEC(pContext->pProvokingVertex)->specular );
CLAMP8888( Col0, Col0, Spec0 );
}
if( Flags & SURFACE_FOGENABLE )
{
// 8 DWORDS.
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V0FloatS_Tag + (vtx*16), vtx);
}
else
{
// 7 DWORDS.
SEND_R3FVFVERTEX_XYZ_STQ(V0FloatS_Tag + (vtx*16), vtx);
}
// 2 DWORDS.
SEND_P3_DATA(ConstantColor,
RGBA_MAKE(RGBA_GETBLUE(Col0),
RGBA_GETGREEN(Col0),
RGBA_GETRED(Col0),
RGBA_GETALPHA(Col0)));
}
// Send the second set of texture coordinates including scale-by-q
if( pContext->iTexStage[1] != -1
&& ( pContext->FVFData.dwTexOffset[0] != pContext->FVFData.dwTexOffset[1]))
{
DISPDBG((DBGLVL,"Sending 2nd texture coordinates"));
if( Flags & SURFACE_PERSPCORRECT )
{
SCALE_BY_Q2( vtx );
}
// 4 DWORDS.
SEND_R3FVFVERTEX_STQ2(V0FloatS1_Tag + (vtx*16), vtx);
}
RENDER_TRAPEZOID(renderCmd);
// 2 DWORDS.
DRAW_TRIANGLE();
P3_DMA_COMMIT_BUFFER();
return pContext->R3flushDueToTexCoordAdjust;
} // __ProcessTri_1Vtx_Generic
//-----------------------------------------------------------------------------
//
// __ProcessTri_3Vtx_Generic
//
//-----------------------------------------------------------------------------
int
__ProcessTri_3Vtx_Generic(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int WireEdgeFlags )
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
TEXCOORDS tc[3];
DWORD q[3];
int forcedQ = 0;
ULONG renderCmd = pContext->RenderCommand;
P3_DMA_DEFS();
GET_TEXCOORDS();
if( __BackfaceCullAndMipMap( pContext, pv, tc ))
return 1;
if( Flags & SURFACE_PERSPCORRECT )
{
q[0] = *(DWORD *)&(pv[0]->rhw);
q[1] = *(DWORD *)&(pv[1]->rhw);
q[2] = *(DWORD *)&(pv[2]->rhw);
// Check for equal Q's
if((( q[0] ^ q[1] ) | ( q[1] ^ q[2] )) == 0 )
{
// Force to 1.0f
forcedQ = q[0] = q[1] = q[2] = 0x3f800000;
}
else
{
SCALE_BY_Q( 0 );
SCALE_BY_Q( 1 );
SCALE_BY_Q( 2 );
}
}
else
{
q[0] = q[1] = q[2] = 0x3f800000;
}
// Send vertex data including check for flat shading
// Worst case 27 DWORDS
P3_DMA_GET_BUFFER_ENTRIES(29);
if( pContext->Flags & SURFACE_GOURAUD )
{
if( Flags & SURFACE_TEXTURING )
{
// 9 DWORDs each.
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V2FloatS_Tag, 2);
}
else
{
// 6 DWORDs each.
SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ_RGBA_SFOG(V2FloatS_Tag, 2);
}
}
else
{
DWORD Col0 = FVFCOLOR(pContext->pProvokingVertex)->color;
if( Flags & SURFACE_SPECULAR )
{
DWORD Spec0 = GET_SPEC( FVFSPEC(pContext->pProvokingVertex)->specular );
CLAMP8888( Col0, Col0, Spec0 );
}
if( Flags & SURFACE_TEXTURING )
{
if( Flags & SURFACE_FOGENABLE )
{
// 8 DWORDs each.
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V2FloatS_Tag, 2);
}
else
{
// 7 DWORDs each.
SEND_R3FVFVERTEX_XYZ_STQ(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_STQ(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ_STQ(V2FloatS_Tag, 2);
}
}
else
{
if( Flags & SURFACE_FOGENABLE )
{
// 5 DWORDs each.
SEND_R3FVFVERTEX_XYZ_FOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_FOG(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ_FOG(V2FloatS_Tag, 2);
}
else
{
// 4 DWORDs each.
SEND_R3FVFVERTEX_XYZ(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ(V1FloatS_Tag, 1);
SEND_R3FVFVERTEX_XYZ(V2FloatS_Tag, 2);
}
}
SEND_P3_DATA(ConstantColor,
RGBA_MAKE(RGBA_GETBLUE(Col0),
RGBA_GETGREEN(Col0),
RGBA_GETRED(Col0),
RGBA_GETALPHA(Col0)));
}
// Send the second set of texture coordinates including scale-by-q
if( pContext->iTexStage[1] != -1
&& ( pContext->FVFData.dwTexOffset[0] != pContext->FVFData.dwTexOffset[1]))
{
DISPDBG((DBGLVL,"Sending 2nd texture coordinates"));
if( Flags & SURFACE_PERSPCORRECT )
{
SCALE_BY_Q2( 0 );
SCALE_BY_Q2( 1 );
SCALE_BY_Q2( 2 );
}
// 12 DWORDS
P3_DMA_COMMIT_BUFFER();
P3_DMA_GET_BUFFER_ENTRIES(14);
// 4 DWORDs each.
SEND_R3FVFVERTEX_STQ2(V0FloatS1_Tag, 0);
SEND_R3FVFVERTEX_STQ2(V1FloatS1_Tag, 1);
SEND_R3FVFVERTEX_STQ2(V2FloatS1_Tag, 2);
}
RENDER_TRAPEZOID(renderCmd);
DRAW_TRIANGLE();
P3_DMA_COMMIT_BUFFER();
return ( pContext->R3flushDueToTexCoordAdjust | forcedQ );
} // __ProcessTri_3Vtx_Generic
//-----------------------------------------------------------------------------
//
// __ProcessTri_1Vtx_Wire
//
//-----------------------------------------------------------------------------
int
__ProcessTri_1Vtx_Wire(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int vtx )
{
DISPDBG((WRNLVL,"WE SHOULDN'T DO __ProcessTri_1Vtx_Wire"));
return 1;
} // __ProcessTri_1Vtx_Wire
//-----------------------------------------------------------------------------
//
// __ProcessTri_3Vtx_Wire
//
//-----------------------------------------------------------------------------
int
__ProcessTri_3Vtx_Wire(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int WireEdgeFlags )
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
TEXCOORDS tc[3];
int i;
DWORD q[3];
ULONG renderCmd = pContext->RenderCommand;
const int edges[] = { SIDE_0, SIDE_1, SIDE_2 };
P3_DMA_DEFS();
GET_TEXCOORDS();
if( __BackfaceCullAndMipMap( pContext, pv, tc ))
return 1;
RENDER_LINE(renderCmd);
if( Flags & SURFACE_PERSPCORRECT )
{
q[0] = *(DWORD *)&(pv[0]->rhw);
q[1] = *(DWORD *)&(pv[1]->rhw);
q[2] = *(DWORD *)&(pv[2]->rhw);
SCALE_BY_Q( 0 );
SCALE_BY_Q( 1 );
SCALE_BY_Q( 2 );
if(pContext->iTexStage[1] != -1 )
{
SCALE_BY_Q2( 0 );
SCALE_BY_Q2( 1 );
SCALE_BY_Q2( 2 );
}
}
// Send vertex data including check for flat shading
for( i = 0; i < 3; i++ )
{
int v0, v1;
v0 = i;
v1 = i + 1;
if( v1 == 3 )
v1 = 0;
if( WireEdgeFlags & edges[i] )
{
P3_DMA_GET_BUFFER_ENTRIES(30);
if( pContext->Flags & SURFACE_GOURAUD )
{
// 9 DWORDs each.
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V0FloatS_Tag, v0);
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V1FloatS_Tag, v1);
}
else
{
DWORD Col0 = FVFCOLOR(pContext->pProvokingVertex)->color;
if( Flags & SURFACE_SPECULAR )
{
DWORD Spec0 = GET_SPEC( FVFSPEC(pContext->pProvokingVertex)->specular );
CLAMP8888( Col0, Col0, Spec0 );
}
if( Flags & SURFACE_FOGENABLE )
{
// 6 DWORDs each.
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V0FloatS_Tag, v0);
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V1FloatS_Tag, v1);
}
else
{
// 7 DWORDs each.
SEND_R3FVFVERTEX_XYZ_STQ(V0FloatS_Tag, v0);
SEND_R3FVFVERTEX_XYZ_STQ(V1FloatS_Tag, v1);
}
SEND_P3_DATA(ConstantColor,
RGBA_MAKE(RGBA_GETBLUE(Col0),
RGBA_GETGREEN(Col0),
RGBA_GETRED(Col0),
RGBA_GETALPHA(Col0)));
}
// Send the second set of texture coordinates
if( pContext->iTexStage[1] != -1
&& ( pContext->FVFData.dwTexOffset[0] != pContext->FVFData.dwTexOffset[1] ))
{
// 4 DWORDs each.
SEND_R3FVFVERTEX_STQ2(V0FloatS1_Tag, v0);
SEND_R3FVFVERTEX_STQ2(V1FloatS1_Tag, v1);
}
DRAW_LINE();
P3_DMA_COMMIT_BUFFER();
}
}
return 1;
} // __ProcessTri_3Vtx_Wire
//-----------------------------------------------------------------------------
//
// __ProcessTri_1Vtx_Point
//
//-----------------------------------------------------------------------------
int
__ProcessTri_1Vtx_Point(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int vtx )
{
DISPDBG((WRNLVL,"WE SHOULDN'T DO __ProcessTri_1Vtx_Wire"));
return 1;
} // __ProcessTri_1Vtx_Point
//-----------------------------------------------------------------------------
//
// __ProcessTri_3Vtx_Point
//
//-----------------------------------------------------------------------------
int
__ProcessTri_3Vtx_Point(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int WireEdgeFlags )
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
TEXCOORDS tc[3];
int i;
DWORD q[3];
ULONG renderCmd = pContext->RenderCommand;
const int edges[] = { SIDE_0, SIDE_1, SIDE_2 };
P3_DMA_DEFS();
GET_TEXCOORDS();
if( __BackfaceCullAndMipMap( pContext, pv, tc ))
return 1;
RENDER_POINT(renderCmd);
if( Flags & SURFACE_PERSPCORRECT )
{
q[0] = *(DWORD *)&(pv[0]->rhw);
q[1] = *(DWORD *)&(pv[1]->rhw);
q[2] = *(DWORD *)&(pv[2]->rhw);
SCALE_BY_Q( 0 );
SCALE_BY_Q( 1 );
SCALE_BY_Q( 2 );
if(pContext->iTexStage[1] != -1)
{
SCALE_BY_Q2( 0 );
SCALE_BY_Q2( 1 );
SCALE_BY_Q2( 2 );
}
}
// Send vertex data including check for flat shading
for( i = 0; i < 3; i++ )
{
int v0, v1;
v0 = i;
v1 = i + 1;
if( v1 == 3 )
v1 = 0;
if( WireEdgeFlags & edges[i] )
{
P3_DMA_GET_BUFFER_ENTRIES( 16 );
if( pContext->Flags & SURFACE_GOURAUD )
{
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V0FloatS_Tag, v0);
}
else
{
DWORD Col0 = FVFCOLOR(pContext->pProvokingVertex)->color;
if( Flags & SURFACE_SPECULAR )
{
DWORD Spec0 = GET_SPEC( FVFSPEC(pContext->pProvokingVertex)->specular );
CLAMP8888( Col0, Col0, Spec0 );
}
if( Flags & SURFACE_FOGENABLE )
{
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V0FloatS_Tag, v0);
}
else
{
SEND_R3FVFVERTEX_XYZ_STQ(V0FloatS_Tag, v0);
}
SEND_P3_DATA(ConstantColor,
RGBA_MAKE(RGBA_GETBLUE(Col0),
RGBA_GETGREEN(Col0),
RGBA_GETRED(Col0),
RGBA_GETALPHA(Col0)));
}
// Send the second set of texture coordinates
if( pContext->iTexStage[1] != -1
&& ( pContext->FVFData.dwTexOffset[0] != pContext->FVFData.dwTexOffset[1]))
{
DISPDBG((DBGLVL,"Sending 2nd texture coordinates"));
SEND_R3FVFVERTEX_STQ2(V0FloatS1_Tag, v0);
}
DRAW_POINT();
P3_DMA_COMMIT_BUFFER();
}
}
return 1;
} // __ProcessTri_3Vtx_Point
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_TriangleList
//
// Render D3DDP2OP_TRIANGLELIST triangles
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_TriangleList(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex, i;
D3DTLVERTEX *pv[3];
DBG_ENTRY(_D3D_R3_DP2_TriangleList);
dwIndex = ((D3DHAL_DP2TRIANGLELIST*)lpPrim)->wVStart;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
pv[2] = LP_FVF_NXT_VTX(pv[1]);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex + 3*dwPrimCount - 1);
pContext->dwProvokingVertex = 0;
for( i = 0; i < dwPrimCount; i++ )
{
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
(*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
pv[0] = LP_FVF_NXT_VTX(pv[2]);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
pv[2] = LP_FVF_NXT_VTX(pv[1]);
}
DBG_EXIT(_D3D_R3_DP2_TriangleList,0);
} // _D3D_R3_DP2_TriangleList
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_TriangleFan
//
// Render a D3DDP2OP_TRIANGLEFAN triangle
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_TriangleFan(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex, i;
D3DTLVERTEX *pv[3];
int vtx, lastVtx, bCulled;
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_TriangleFan);
lastVtx = vtx = 2;
dwIndex = ((D3DHAL_DP2TRIANGLEFAN*)lpPrim)->wVStart;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
pv[2] = LP_FVF_NXT_VTX(pv[1]);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex + dwPrimCount + 1);
pContext->dwProvokingVertex = 1;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
bCulled = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
for( i = 1; i < dwPrimCount; i++ )
{
vtx ^= 3; // 2 -> 1, 1 -> 2
FLIP_CCW_CW_CULLING(pContext);
pv[vtx] = LP_FVF_NXT_VTX(pv[lastVtx]);
pContext->dwProvokingVertex = lastVtx;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
if( bCulled )
bCulled = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
else
bCulled = (*pContext->pRendTri_1V)( pContext, pv, vtx );
lastVtx = vtx;
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_TriangleFan,0);
} // _D3D_R3_DP2_TriangleFan
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_TriangleFanImm
//
// Render D3DDP2OP_TRIANGLEFAN_IMM triangles
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_TriangleFanImm(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[3];
DWORD i, dwEdgeFlags, eFlags;
int vtx, lastVtx, bCulled;
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_TriangleFanImm);
lastVtx = vtx = 2;
// Edge flags are used for wireframe fillmode
dwEdgeFlags = ((D3DHAL_DP2TRIANGLEFAN_IMM *)lpPrim)->dwEdgeFlags;
lpPrim += sizeof(D3DHAL_DP2TRIANGLEFAN_IMM);
// Vertices in an IMM instruction are stored in the
// command buffer and are DWORD aligned
lpPrim = (LPBYTE)((ULONG_PTR)( lpPrim + 3 ) & ~3 );
pv[0] = (LPD3DTLVERTEX)lpPrim;
pv[1] = LP_FVF_NXT_VTX(pv[0]);
pv[2] = LP_FVF_NXT_VTX(pv[1]);
// since data is in the command buffer, we've already verified it as valid
// Build up edge flags for the next single primitive
eFlags = ( dwEdgeFlags & 1 ) ? SIDE_0 : 0;
eFlags |= ( dwEdgeFlags & 2 ) ? SIDE_1 : 0;
dwEdgeFlags >>= 2;
pContext->dwProvokingVertex = 1;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
bCulled = (*pContext->pRendTri_3V)( pContext, pv, eFlags);
for( i = 1; i < dwPrimCount; i++ )
{
// 2 -> 1, 1 -> 2
vtx ^= 3;
FLIP_CCW_CW_CULLING(pContext);
pv[vtx] = LP_FVF_NXT_VTX(pv[lastVtx]);
if( i == ( dwPrimCount - 1 ))
{
eFlags = ( dwEdgeFlags & 1 ) ? SIDE_1 : 0;
eFlags |= ( dwEdgeFlags & 2 ) ? SIDE_2 : 0;
}
else
{
eFlags = ( dwEdgeFlags & 1 ) ? SIDE_1 : 0;
dwEdgeFlags >>= 1;
}
pContext->dwProvokingVertex = lastVtx;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
if( bCulled )
bCulled = (*pContext->pRendTri_3V)( pContext, pv, eFlags);
else
bCulled = (*pContext->pRendTri_1V)( pContext, pv, vtx );
lastVtx = vtx;
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_TriangleFanImm,0);
} // _D3D_R3_DP2_TriangleFanImm
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_TriangleStrip
//
// Render D3DDP2OP_TRIANGLESTRIP triangles
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_TriangleStrip(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex, i;
D3DTLVERTEX *pv[3];
int vtx_a, vtx_b, lastVtx, bCulled;
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_TriangleStrip);
dwIndex = ((D3DHAL_DP2TRIANGLEFAN*)lpPrim)->wVStart;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
pv[2] = LP_FVF_NXT_VTX(pv[1]);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex + dwPrimCount + 1);
pContext->dwProvokingVertex = 0;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
bCulled = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
lastVtx = 2;
INIT_VERTEX_INDICES(pContext, vtx_a, vtx_b);
for( i = 1; i < dwPrimCount; i++ )
{
FLIP_CCW_CW_CULLING(pContext);
pv[vtx_a] = LP_FVF_NXT_VTX(pv[lastVtx]);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
if( bCulled )
bCulled = (*pContext->pRendTri_3V)( pContext, pv,ALL_SIDES);
else
bCulled = (*pContext->pRendTri_1V)( pContext, pv, vtx_a );
lastVtx = vtx_a;
CYCLE_VERTEX_INDICES(pContext, vtx_a, vtx_b);
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_TriangleStrip,0);
} // _D3D_R3_DP2_TriangleStrip
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleStrip
//
// Render D3DDP2OP_INDEXEDTRIANGLESTRIP triangles
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleStrip(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i;
WORD wVStart;
D3DTLVERTEX *pv[3];
int vtx_a, vtx_b, bCulled;
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleStrip);
wVStart = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
lpPrim += sizeof(D3DHAL_DP2STARTVERTEX);
dwIndex0 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[0];
dwIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[1];
dwIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[2];
lpVertices = LP_FVF_VERTEX(lpVertices, wVStart);
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex2);
pContext->dwProvokingVertex = 0;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
bCulled = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
lpPrim += sizeof(WORD);
INIT_VERTEX_INDICES(pContext, vtx_a, vtx_b);
for( i = 1; i < dwPrimCount; i++ )
{
FLIP_CCW_CW_CULLING(pContext);
dwIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[2];
pv[vtx_a] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex2);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
if( bCulled )
bCulled = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
else
bCulled = (*pContext->pRendTri_1V)( pContext, pv, vtx_a );
lpPrim += sizeof(WORD);
CYCLE_VERTEX_INDICES(pContext, vtx_a, vtx_b);
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleStrip,0);
} // _D3D_R3_DP2_IndexedTriangleStrip
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleFan
//
// Render D3DDP2OP_INDEXEDTRIANGLEFAN triangles
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleFan(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i;
WORD wVStart;
D3DTLVERTEX *pv[3];
int vtx, lastVtx, bCulled;
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleFan);
wVStart = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
lpPrim += sizeof(D3DHAL_DP2STARTVERTEX);
dwIndex0 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[0];
dwIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[1];
dwIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[2];
lastVtx = vtx = 2;
pv[0] = LP_FVF_VERTEX(lpVertices, wVStart + dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, wVStart + dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, wVStart + dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, (DWORD)(wVStart) + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, (DWORD)(wVStart) + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, (DWORD)(wVStart) + dwIndex2);
pContext->dwProvokingVertex = 1;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
bCulled = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
lpPrim += sizeof(WORD);
for( i = 1; i < dwPrimCount; i++ )
{
// 2 -> 1, 1 -> 2
vtx ^= 3;
FLIP_CCW_CW_CULLING(pContext);
dwIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLEFAN*)lpPrim)->wV[2];
pv[vtx] = LP_FVF_VERTEX(lpVertices, wVStart + dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart + dwIndex2);
pContext->dwProvokingVertex = lastVtx;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
if( bCulled )
bCulled = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
else
bCulled = (*pContext->pRendTri_1V)( pContext, pv, vtx );
lastVtx = vtx;
lpPrim += sizeof(WORD);
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleFan,0);
} // _D3D_R3_DP2_IndexedTriangleFan
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleList
//
// Render D3DDP2OP_INDEXEDTRIANGLELIST triangles
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleList(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i, primData;
WORD wFlags;
D3DTLVERTEX *pv[3];
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleList);
pContext->dwProvokingVertex = 0;
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex0 = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wV1;
dwIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wV2;
dwIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wV3;
wFlags = ((D3DHAL_DP2INDEXEDTRIANGLELIST*)lpPrim)->wFlags;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex2);
lpPrim += sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
(*pContext->pRendTri_3V)( pContext, pv, wFlags);
}
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleList,0);
} // _D3D_R3_DP2_IndexedTriangleList
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleList2
//
// Render D3DDP2OP_INDEXEDTRIANGLELIST2 triangles
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleList2(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i;
WORD wVStart;
D3DTLVERTEX *pv[3];
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleList2);
wVStart = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
lpPrim += sizeof(D3DHAL_DP2STARTVERTEX);
lpVertices = LP_FVF_VERTEX(lpVertices, wVStart);
pContext->dwProvokingVertex = 0;
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex0 = ((D3DHAL_DP2INDEXEDTRIANGLELIST2*)lpPrim)->wV1;
dwIndex1 = ((D3DHAL_DP2INDEXEDTRIANGLELIST2*)lpPrim)->wV2;
dwIndex2 = ((D3DHAL_DP2INDEXEDTRIANGLELIST2*)lpPrim)->wV3;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, (DWORD)wVStart + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, (DWORD)wVStart + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, (DWORD)wVStart + dwIndex2);
lpPrim += sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST2);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
(*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES);
}
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleList2,0);
} // _D3D_R3_DP2_IndexedTriangleList2
//-----------------------------------------------------------------------------
//
// __ProcessLine
//
// Render a single line
//
//-----------------------------------------------------------------------------
void
__ProcessLine(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
D3DTLVERTEX *pProvokingVtx)
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
TEXCOORDS tc[2];
DWORD q[2];
ULONG renderCmd = pContext->RenderCommand;
P3_DMA_DEFS();
RENDER_LINE(renderCmd);
GET_TC(0); GET_TC(1);
P3_DMA_GET_BUFFER_ENTRIES(22);
if (pContext->RenderStates[D3DRENDERSTATE_LINEPATTERN])
{
// if we are line stippling then reset rendering for each line
SEND_P3_DATA( UpdateLineStippleCounters , 0);
}
if( Flags & SURFACE_PERSPCORRECT )
{
q[0] = *(DWORD *)&(pv[0]->rhw);
q[1] = *(DWORD *)&(pv[1]->rhw);
SCALE_BY_Q( 0 );
SCALE_BY_Q( 1 );
}
else
{
q[0] = q[1] = 0;
}
if (Flags & SURFACE_GOURAUD)
{
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG(V1FloatS_Tag, 1);
}
else
{
DWORD Col0 = FVFCOLOR(pProvokingVtx)->color;
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V0FloatS_Tag, 0);
SEND_R3FVFVERTEX_XYZ_STQ_FOG(V1FloatS_Tag, 1);
if( pContext->Flags & SURFACE_SPECULAR )
{
DWORD Spec0 = GET_SPEC( FVFSPEC(pProvokingVtx)->specular );
CLAMP8888( Col0, Col0, Spec0 );
}
SEND_P3_DATA(ConstantColor, RGBA_MAKE(RGBA_GETBLUE(Col0),
RGBA_GETGREEN(Col0),
RGBA_GETRED(Col0),
RGBA_GETALPHA(Col0)));
}
DRAW_LINE();
P3_DMA_COMMIT_BUFFER();
} // __ProcessLine
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_LineList
//
// Render D3DDP2OP_LINELIST lines
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_LineList(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
WORD wVStart;
DWORD i;
DBG_ENTRY(_D3D_R3_DP2_LineList);
wVStart = ((D3DHAL_DP2LINELIST*)lpPrim)->wVStart;
pv[0] = LP_FVF_VERTEX(lpVertices, wVStart);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen,
(LONG)wVStart + 2*dwPrimCount - 1)
for( i = 0; i < dwPrimCount; i++ )
{
__ProcessLine(pContext, pv, pv[0]);
pv[0] = LP_FVF_NXT_VTX(pv[1]);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
}
DBG_EXIT(_D3D_R3_DP2_LineList,0);
} // _D3D_R3_DP2_LineList
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_LineListImm
//
// Render D3DDP2OP_LINELIST_IMM lines
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_LineListImm(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
DWORD i;
DBG_ENTRY(_D3D_R3_DP2_LineListImm);
pv[0] = (LPD3DTLVERTEX)lpPrim;
pv[1] = LP_FVF_NXT_VTX(pv[0]);
// since data is in the command buffer, we've already verified it as valid
for( i = 0; i < dwPrimCount; i++ )
{
__ProcessLine(pContext, pv, pv[0]);
pv[0] = LP_FVF_NXT_VTX(pv[1]);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
}
DBG_EXIT(_D3D_R3_DP2_LineListImm,0);
} // _D3D_R3_DP2_LineListImm
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_LineStrip
//
// Render D3DDP2OP_LINESTRIP lines
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_LineStrip(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
WORD wVStart;
DWORD i;
DBG_ENTRY(_D3D_R3_DP2_LineStrip);
wVStart = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
pv[0] = LP_FVF_VERTEX(lpVertices, wVStart);
pv[1] = LP_FVF_NXT_VTX(pv[0]);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart + dwPrimCount);
for( i = 0; i < dwPrimCount; i++ )
{
__ProcessLine(pContext, pv, pv[0]);
pv[0] = pv[1];
pv[1] = LP_FVF_NXT_VTX(pv[1]);
}
DBG_EXIT(_D3D_R3_DP2_LineStrip,0);
} // _D3D_R3_DP2_LineStrip
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedLineList
//
// Render D3DDP2OP_INDEXEDLINELIST lines
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedLineList(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
DWORD primData, dwIndex0, dwIndex1, i;
DBG_ENTRY(_D3D_R3_DP2_IndexedLineList);
for( i = 0; i < dwPrimCount; i++ )
{
primData = *(DWORD *)lpPrim;
dwIndex0 = ( primData >> 0 ) & 0xffff;
dwIndex1 = ( primData >> 16 );
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex1);
lpPrim += sizeof(D3DHAL_DP2INDEXEDLINELIST);
__ProcessLine(pContext, pv, pv[0]);
}
DBG_EXIT(_D3D_R3_DP2_IndexedLineList,0);
} // _D3D_R3_DP2_IndexedLineList
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedLineList2
//
// Render D3DDP2OP_INDEXEDLINELIST2 lines
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedLineList2(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
DWORD primData, i;
WORD wVStart, dwIndex0, dwIndex1;
DBG_ENTRY(_D3D_R3_DP2_IndexedLineList2);
wVStart = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
lpVertices = LP_FVF_VERTEX(lpVertices, wVStart);
lpPrim += sizeof(D3DHAL_DP2STARTVERTEX);
for( i = 0; i < dwPrimCount; i++ )
{
primData = *(DWORD *)lpPrim;
dwIndex0 = ( (WORD)(primData >> 0) ) & 0xffff;
dwIndex1 = ( (WORD)(primData >> 16) );
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex0 + wVStart);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex1 + wVStart);
lpPrim += sizeof(D3DHAL_DP2INDEXEDLINELIST);
__ProcessLine(pContext, pv, pv[0]);
}
DBG_EXIT(_D3D_R3_DP2_IndexedLineList2,0);
} // _D3D_R3_DP2_IndexedLineList2
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedLineStrip
//
// Render D3DDP2OP_INDEXEDLINESTRIP lines
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedLineStrip(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
WORD wVStart, dwIndex, *pwIndx;
DWORD i;
DBG_ENTRY(_D3D_R3_DP2_IndexedLineStrip);
wVStart = ((D3DHAL_DP2STARTVERTEX*)lpPrim)->wVStart;
lpVertices = LP_FVF_VERTEX(lpVertices, wVStart);
lpPrim += sizeof(D3DHAL_DP2STARTVERTEX);
pwIndx = (WORD *)lpPrim;
dwIndex = *pwIndx++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex);
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex = *pwIndx++;
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex);
__ProcessLine(pContext, pv, pv[0]);
pv[0] = pv[1];
}
DBG_EXIT(_D3D_R3_DP2_IndexedLineStrip,0);
} // _D3D_R3_DP2_IndexedLineStrip
//-----------------------------------------------------------------------------
//
// __ProcessPoints
//
// Render a set points specified by adjacent FVF vertices
//
//-----------------------------------------------------------------------------
void
__ProcessPoints(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
DWORD dwCount)
{
P3_THUNKEDDATA* pThisDisplay = pContext->pThisDisplay;
DWORD Flags = pContext->Flags;
DWORD q[1];
TEXCOORDS tc[1];
ULONG renderCmd = pContext->RenderCommand;
DWORD j;
D3DTLVERTEX *ptmpV;
P3_DMA_DEFS();
ptmpV = pv[0];
RENDER_LINE(renderCmd);
q[0] = 0;
for( j = 0; j < dwCount; j++ )
{
P3_DMA_GET_BUFFER_ENTRIES( 20 );
GET_TC(0);
if( Flags & SURFACE_PERSPCORRECT )
{
q[0] = *(DWORD *)&(pv[0]->rhw);
SCALE_BY_Q( 0 );
}
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG_POINT(V0FloatS_Tag, 0, FALSE);
SEND_R3FVFVERTEX_XYZ_STQ_RGBA_SFOG_POINT(V1FloatS_Tag, 0, TRUE);
DRAW_LINE();
P3_DMA_COMMIT_BUFFER();
pv[0] = LP_FVF_NXT_VTX(pv[0]);
}
pv[0] = ptmpV;
} // __ProcessPoints
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_Points
//
// Render D3DDP2OP_POINTS points
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_Points(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[1];
WORD wVStart, wCount;
DWORD i;
DBG_ENTRY(_D3D_R3_DP2_Points);
for( i = 0; i < dwPrimCount; i++ )
{
wVStart = ((D3DHAL_DP2POINTS*)lpPrim)->wVStart;
wCount = ((D3DHAL_DP2POINTS*)lpPrim)->wCount;
lpVertices = LP_FVF_VERTEX(lpVertices, wVStart);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart + wCount - 1);
pv[0] = LP_FVF_VERTEX(lpVertices, 0);
__ProcessPoints(pContext, pv, wCount);
lpPrim += sizeof(D3DHAL_DP2POINTS);
}
DBG_EXIT(_D3D_R3_DP2_Points,0);
} // _D3D_R3_DP2_Points
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_Points_DWCount
//
// Render D3DDP2OP_POINTS points for DX8 case
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_Points_DWCount(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[1];
WORD wVStart;
DWORD i;
DBG_ENTRY(_D3D_R3_DP2_Points_DWCount);
wVStart = ((D3DHAL_DP2POINTS*)lpPrim)->wVStart;
lpVertices = LP_FVF_VERTEX(lpVertices, wVStart);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart + dwPrimCount - 1);
pv[0] = LP_FVF_VERTEX(lpVertices, 0);
__ProcessPoints(pContext, pv, dwPrimCount);
DBG_EXIT(_D3D_R3_DP2_Points_DWCount,0);
} // _D3D_R3_DP2_Points_DWCount
#if DX8_POINTSPRITES
#define SPRITETEXCOORDMAX 1.0f
//Size of maximum FVF that we can get. Used for temporary storage
typedef BYTE P3FVFMAXVERTEX[ 3 * sizeof( D3DVALUE ) + // Position coordinates
5 * 4 + // D3DFVF_XYZB5
sizeof( D3DVALUE ) + // FVF_TRANSFORMED
3 * sizeof( D3DVALUE ) + // Normals
sizeof( DWORD ) + // RESERVED1
sizeof( DWORD ) + // Diffuse color
sizeof( D3DCOLOR ) + // Specular color
sizeof( D3DVALUE ) + // Point sprite size
4 * 8 * sizeof( D3DVALUE ) // 8 sets of 4D texture coordinates
];
//-----------------------------------------------------------------------------
//
// __Render_One_PointSprite
//
// Render a point sprite with FVF vertexes when the point sprite enable is on
//
// Note: this is not the most optimized implementation possible for
// pointprites on this hw. We are merely following the definition.
// Later implementation will be optimized.
//-----------------------------------------------------------------------------
void
__Render_One_PointSprite(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *lpVertex)
{
// notice these are BYTE[], so its not necessary to write &fvfVUL to
// get the address of fvfVUL (just write fvfVUL)
P3FVFMAXVERTEX fvfVUL, fvfVUR, fvfVLL, fvfVLR ;
D3DVALUE fPntSize, fPntSizeHalf, fD2, fD, fScalePntSize, fFac;
D3DTLVERTEX *pv[3];
FVFOFFSETS OrigFVF;
BOOL bTexturingWOTexCoords = FALSE;
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(__Render_One_PointSprite);
// Get point sprite size , if FVF data comes with it, grab it from there
if (pContext->FVFData.dwPntSizeOffset)
{
fPntSize = FVFPSIZE(lpVertex)->psize;
DISPDBG((DBGLVL,"FVF Data fPntSize = %d",(LONG)(fPntSize*1000.0f) ));
}
else
{
fPntSize = pContext->PntSprite.fSize;
DISPDBG((DBGLVL,"RS fPntSize = %d",(LONG)(fPntSize*1000.0f) ));
}
// We don't need to compute the point size according to the scale
// factors and viewport size, etc as we are not a TnL driver.
// See the spec for deatils
// Clamp fPntSize to limits defined by the driver caps (dvMaxPointSize)
// and the D3DRS_POINTSIZE_MIN and D3DRS_POINTSIZE_MAX renderstates
fPntSize = max(pContext->PntSprite.fSizeMin,
fPntSize);
fPntSize = min( min(pContext->PntSprite.fSizeMax,
P3_MAX_POINTSPRITE_SIZE),
fPntSize);
// Divide by 2 to get the amount by which to modify vertex coords
fPntSizeHalf = fPntSize * 0.5f;
// Initialize square vertex values
memcpy( fvfVUL, lpVertex, pContext->FVFData.dwStride);
memcpy( fvfVUR, lpVertex, pContext->FVFData.dwStride);
memcpy( fvfVLL, lpVertex, pContext->FVFData.dwStride);
memcpy( fvfVLR, lpVertex, pContext->FVFData.dwStride);
// Make this a square of size fPntSize
((D3DTLVERTEX *)fvfVUL)->sx -= fPntSizeHalf;
((D3DTLVERTEX *)fvfVUL)->sy -= fPntSizeHalf;
((D3DTLVERTEX *)fvfVUR)->sx += fPntSizeHalf;
((D3DTLVERTEX *)fvfVUR)->sy -= fPntSizeHalf;
((D3DTLVERTEX *)fvfVLL)->sx -= fPntSizeHalf;
((D3DTLVERTEX *)fvfVLL)->sy += fPntSizeHalf;
((D3DTLVERTEX *)fvfVLR)->sx += fPntSizeHalf;
((D3DTLVERTEX *)fvfVLR)->sy += fPntSizeHalf;
// This is for the case in which PntSprite.bEnabled is false
// and we are texturing even if we have no tex coord data in
// the pointsprite vertexes
bTexturingWOTexCoords = (pContext->FVFData.dwNonTexStride ==
pContext->FVFData.dwStride )
&& (!pContext->bTexDisabled);
if (pContext->PntSprite.bEnabled || bTexturingWOTexCoords)
{
// Remember orig FVF offsets in order to fake our own texcoords
OrigFVF = pContext->FVFData;
// We "create" new texturing info in our data in order to
// process vertexes even without texturing coord info
// This is OK since we are using P3FVFMAXVERTEX as the type
// of our temporary data structures for each vertex so we
// can't overflow.
// If stage 0 texture is used
pContext->FVFData.dwTexCount = 1;
pContext->FVFData.dwTexOffset[0] =
pContext->FVFData.dwTexCoordOffset[0] =
pContext->FVFData.dwNonTexStride;
// If stage 1 texture is used
// we can use the same tex coord set since they are equal
pContext->FVFData.dwTexOffset[1] =
pContext->FVFData.dwTexCoordOffset[0];
if (pContext->PntSprite.bEnabled)
{
// Set up texture coordinates according to spec
FVFTEX(fvfVUL, 0)->tu = 0.0f;
FVFTEX(fvfVUL, 0)->tv = 0.0f;
FVFTEX(fvfVUR, 0)->tu = SPRITETEXCOORDMAX;
FVFTEX(fvfVUR, 0)->tv = 0.0f;
FVFTEX(fvfVLL, 0)->tu = 0.0f;
FVFTEX(fvfVLL, 0)->tv = SPRITETEXCOORDMAX;
FVFTEX(fvfVLR, 0)->tu = SPRITETEXCOORDMAX;
FVFTEX(fvfVLR, 0)->tv = SPRITETEXCOORDMAX;
}
else
{
// if we got here then PntSprite.bEnabled is false
// so just make the tex coords == (0,0)
FVFTEX(fvfVUL, 0)->tu = 0.0f;
FVFTEX(fvfVUL, 0)->tv = 0.0f;
FVFTEX(fvfVUR, 0)->tu = 0.0f;
FVFTEX(fvfVUR, 0)->tv = 0.0f;
FVFTEX(fvfVLL, 0)->tu = 0.0f;
FVFTEX(fvfVLL, 0)->tv = 0.0f;
FVFTEX(fvfVLR, 0)->tu = 0.0f;
FVFTEX(fvfVLR, 0)->tv = 0.0f;
}
#if DX8_3DTEXTURES
// Allow for the case of 3D texturing
FVFTEX(fvfVUL, 0)->tw = 0.0f;
FVFTEX(fvfVUR, 0)->tw = 0.0f;
FVFTEX(fvfVLL, 0)->tw = 0.0f;
FVFTEX(fvfVLR, 0)->tw = 0.0f;
#endif
}
// Make sure Culling doesn't prevent pointsprites from rendering
SET_CULLING_TO_NONE(pContext); // culling state was previously saved
// here we are going to send the required quad
pv[0] = (D3DTLVERTEX*)fvfVUL;
pv[1] = (D3DTLVERTEX*)fvfVUR;
pv[2] = (D3DTLVERTEX*)fvfVLL;
__ProcessTri_3Vtx_Generic(pContext, pv, ALL_SIDES);
pv[0] = (D3DTLVERTEX*)fvfVLL;
pv[1] = (D3DTLVERTEX*)fvfVUR;
pv[2] = (D3DTLVERTEX*)fvfVLR;
__ProcessTri_3Vtx_Generic(pContext, pv, ALL_SIDES);
// Restore original Culling settings
RESTORE_CULLING_STATE(pContext);
// Restore original FVF offsets
if (pContext->PntSprite.bEnabled || bTexturingWOTexCoords)
{
pContext->FVFData = OrigFVF;
}
DBG_EXIT(__Render_One_PointSprite, 0);
} // __Render_One_PointSprite
//-----------------------------------------------------------------------------
//
// __ProcessTri_1Vtx_PointSprite
//
//-----------------------------------------------------------------------------
int
__ProcessTri_1Vtx_PointSprite(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int vtx )
{
DISPDBG((WRNLVL,"WE SHOULDN'T DO __ProcessTri_1Vtx_PointSprite"));
return 1;
} // __ProcessTri_1Vtx_PointSprite
//-----------------------------------------------------------------------------
//
// __ProcessTri_3Vtx_PointSprite
//
//-----------------------------------------------------------------------------
int
__ProcessTri_3Vtx_PointSprite(
P3_D3DCONTEXT *pContext,
D3DTLVERTEX *pv[],
int WireEdgeFlags )
{
#if CULL_HERE
if( __BackfaceCullNoTexture( pContext, pv ))
return 1;
#endif
__Render_One_PointSprite(pContext, pv[0]);
__Render_One_PointSprite(pContext, pv[1]);
__Render_One_PointSprite(pContext, pv[2]);
return 1;
} // __ProcessTri_3Vtx_PointSprite
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_PointsSprite_DWCount
//
// Render D3DDP2OP_POINTS points sprites
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_PointsSprite_DWCount(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[1];
WORD wVStart;
DWORD j;
DBG_ENTRY(_D3D_R3_DP2_PointsSprite_DWCount);
wVStart = ((D3DHAL_DP2POINTS*)lpPrim)->wVStart;
lpVertices = LP_FVF_VERTEX(lpVertices, wVStart);
// Check first & last vertex
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, wVStart + dwPrimCount - 1);
pContext->dwProvokingVertex = 0;
for( j = 0; j < dwPrimCount; j++ )
{
pv[0] = LP_FVF_VERTEX(lpVertices, j);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
__Render_One_PointSprite(pContext, pv[0]);
}
DBG_EXIT(_D3D_R3_DP2_PointsSprite_DWCount,0);
} // _D3D_R3_DP2_PointsSprite_DWCount
#endif // DX8_POINTSPRITES
#if DX8_MULTSTREAMS
// Macro to render a single triangle depending on the current Fillmode.
// Notice that for proper line rendering we require one more element in pv (4)
#define RENDER_ONE_TRIANGLE_CYCLE(pContext, dwFillMode, pv, bVtxInvalid, vtx_a)\
{ \
if (dwFillMode == D3DFILL_SOLID) \
{ \
if( bVtxInvalid ) \
bVtxInvalid = (*pContext->pRendTri_3V)( pContext, pv, ALL_SIDES); \
else \
bVtxInvalid = (*pContext->pRendTri_1V)( pContext, pv, vtx_a ); \
} \
else if (dwFillMode == D3DFILL_WIREFRAME) \
{ \
if(!__BackfaceCullNoTexture( pContext, pv )) \
{ \
pv[3] = pv[0]; \
__ProcessLine(pContext, &pv[0], pv[pContext->dwProvokingVertex]);\
__ProcessLine(pContext, &pv[1], pv[pContext->dwProvokingVertex]);\
__ProcessLine(pContext, &pv[2], pv[pContext->dwProvokingVertex]);\
} \
} \
else \
/*#if DX8_POINTSPRITES*/ \
if(IS_POINTSPRITE_ACTIVE(pContext)) \
{ \
__ProcessTri_3Vtx_PointSprite( pContext, pv, ALL_SIDES ); \
} \
else \
/*#endif*/ \
{ \
if(!__BackfaceCullNoTexture( pContext, pv )) \
{ \
__ProcessPoints( pContext, &pv[0], 1); \
__ProcessPoints( pContext, &pv[1], 1); \
__ProcessPoints( pContext, &pv[2], 1); \
} \
} \
}
#define INIT_RENDER_ONE_TRIANGLE(pContext, dwFillMode, pv,VtxInvalid) \
{ \
int vtx_a_local = 0; \
VtxInvalid= 1; \
RENDER_ONE_TRIANGLE_CYCLE(pContext, \
dwFillMode, \
pv, \
VtxInvalid, \
vtx_a_local); \
}
#define RENDER_ONE_TRIANGLE(pContext, dwFillMode, pv) \
{ \
int vtx_a = 0, VtxInvalid= 1; \
RENDER_ONE_TRIANGLE_CYCLE(pContext, \
dwFillMode, \
pv, \
VtxInvalid, \
vtx_a); \
}
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedLineList_MS_16IND
//
// Render D3DDP2OP_INDEXEDLINELIST lines
// 16 bit index streams are assumed
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedLineList_MS_16IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
WORD *pwIndx;
DWORD dwIndex0, dwIndex1, i;
DBG_ENTRY(_D3D_R3_DP2_IndexedLineList_MS_16IND);
pwIndx = (WORD *)lpPrim;
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex0 = *pwIndx++;
dwIndex1 = *pwIndx++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
__ProcessLine( pContext, pv, pv[0]);
}
DBG_EXIT(_D3D_R3_DP2_IndexedLineList_MS_16IND,0);
} // _D3D_R3_DP2_IndexedLineList_MS_16IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedLineStrip_MS_16IND
//
// Render D3DDP2OP_INDEXEDLINESTRIP lines
// 16 bit index streams are assumed
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedLineStrip_MS_16IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
DWORD dwIndex, i;
WORD *pwIndx;
DBG_ENTRY(_D3D_R3_DP2_IndexedLineStrip_MS_32IND);
pwIndx = (WORD *)lpPrim;
dwIndex = *pwIndx++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex);
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex = *pwIndx++;
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex);
__ProcessLine(pContext, pv, pv[0]);
pv[0] = pv[1];
}
DBG_EXIT(_D3D_R3_DP2_IndexedLineStrip_MS_16IND,0);
} // _D3D_R3_DP2_IndexedLineStrip_MS_16IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleList_MS_16IND
//
// Render D3DDP2OP_INDEXEDTRIANGLELIST triangles
// 16 bit index streams are assumed
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleList_MS_16IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i;
D3DTLVERTEX *pv[4];
WORD *pwIndexData;
DWORD dwFillMode = pContext->RenderStates[D3DRS_FILLMODE];
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleList_MS_16IND);
DISPDBG((DBGLVL,"pContext = 0x%x dwPrimCount=%d lpPrim=0x%x lpVertices=0x%x "
"IdxOffset=%d dwVertexBufferLen=%d ",
pContext,(DWORD)dwPrimCount,lpPrim,lpVertices,
IdxOffset, dwVertexBufferLen));
pwIndexData = (WORD *)lpPrim;
pContext->dwProvokingVertex = 0;
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex0 = *pwIndexData++;
dwIndex1 = *pwIndexData++;
dwIndex2 = *pwIndexData++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
RENDER_ONE_TRIANGLE(pContext,dwFillMode,pv);
}
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleList_MS_16IND,0);
} // _D3D_R3_DP2_IndexedTriangleList_MS_16IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleStrip_MS_16IND
//
// Render D3DDP2OP_INDEXEDTRIANGLESTRIP triangles
// 16 bit index streams are assumed
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleStrip_MS_16IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i;
D3DTLVERTEX *pv[4];
int vtx_a, vtx_b, bCulled;
WORD *pwIndexData;
DWORD dwFillMode = pContext->RenderStates[D3DRS_FILLMODE];
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleStrip_MS_16IND);
pwIndexData = (WORD *)lpPrim;
dwIndex0 = *pwIndexData++;
dwIndex1 = *pwIndexData++;
dwIndex2 = *pwIndexData++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->dwProvokingVertex = 0;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
INIT_RENDER_ONE_TRIANGLE(pContext,dwFillMode,pv,bCulled);
lpPrim += sizeof(WORD);
INIT_VERTEX_INDICES(pContext, vtx_a, vtx_b);
for( i = 1; i < dwPrimCount; i++ )
{
FLIP_CCW_CW_CULLING(pContext);
dwIndex2 = *pwIndexData++;
pv[vtx_a] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex2);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
RENDER_ONE_TRIANGLE_CYCLE(pContext,
dwFillMode,
pv,
bCulled,
vtx_a);
CYCLE_VERTEX_INDICES(pContext, vtx_a, vtx_b);
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleStrip_MS_16IND,0);
} // _D3D_R3_DP2_IndexedTriangleStrip_MS_16IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleFan_MS_16IND
//
// Render D3DDP2OP_INDEXEDTRIANGLEFAN triangles in
// 16 bit index streams are assumed
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleFan_MS_16IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i;
D3DTLVERTEX *pv[4];
int vtx, lastVtx, bCulled;
WORD *pwIndexData;
DWORD dwFillMode = pContext->RenderStates[D3DRS_FILLMODE];
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleFan_MS_16IND);
pwIndexData = (WORD *)lpPrim;
dwIndex0 = *pwIndexData++;
dwIndex1 = *pwIndexData++;
dwIndex2 = *pwIndexData++;
lastVtx = vtx = 2;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->dwProvokingVertex = 1;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
INIT_RENDER_ONE_TRIANGLE(pContext,dwFillMode,pv,bCulled);
lpPrim += sizeof(WORD);
for( i = 1; i < dwPrimCount; i++ )
{
// 2 -> 1, 1 -> 2
vtx ^= 3;
FLIP_CCW_CW_CULLING(pContext);
dwIndex2 = *pwIndexData++;
pv[vtx] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->dwProvokingVertex = lastVtx;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
RENDER_ONE_TRIANGLE_CYCLE(pContext,
dwFillMode,
pv,
bCulled,
vtx);
lastVtx = vtx;
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleFan_MS_16IND,0);
} // _D3D_R3_DP2_IndexedTriangleFan_MS_16IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedLineList_MS_32IND
//
// Render D3DDP2OP_INDEXEDLINELIST lines
// Indices come as 32-bit entities ( DX7 only uses 16-bit indices)
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedLineList_MS_32IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
DWORD *pdwIndx, dwIndex0, dwIndex1, i;
DBG_ENTRY(_D3D_R3_DP2_IndexedLineList_MS_32IND);
pdwIndx = (DWORD *)lpPrim;
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex0 = *pdwIndx++;
dwIndex1 = *pdwIndx++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
__ProcessLine(pContext, pv, pv[0]);
}
DBG_EXIT(_D3D_R3_DP2_IndexedLineList_MS_32IND,0);
} // _D3D_R3_DP2_IndexedLineList_MS_32IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedLineStrip_MS_32IND
//
// Render D3DDP2OP_INDEXEDLINESTRIP lines
// Indices come as 32-bit entities ( DX7 only uses 16-bit indices)
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedLineStrip_MS_32IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
D3DTLVERTEX *pv[2];
DWORD dwIndex, *pdwIndx, i;
DBG_ENTRY(_D3D_R3_DP2_IndexedLineStrip_MS_32IND);
pdwIndx = (DWORD *)lpPrim;
dwIndex = *pdwIndx++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex);
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex = *pdwIndx++;
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex);
__ProcessLine(pContext, pv, pv[0]);
pv[0] = pv[1];
}
DBG_EXIT(_D3D_R3_DP2_IndexedLineStrip_MS_32IND,0);
} // _D3D_R3_DP2_IndexedLineStrip_MS_32IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleList_MS_32IND
//
// Render D3DDP2OP_INDEXEDTRIANGLELIST triangles
// Indices come as 32-bit entities ( DX7 only uses 16-bit indices)
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleList_MS_32IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, *pdwIndexData, i;
D3DTLVERTEX *pv[4];
DWORD dwFillMode = pContext->RenderStates[D3DRS_FILLMODE];
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleList_MS_32IND);
DISPDBG((DBGLVL,"pContext = 0x%x dwPrimCount=%d lpPrim=0x%x lpVertices=0x%x "
"IdxOffset=%d dwVertexBufferLen=%d ",
pContext,(DWORD)dwPrimCount,lpPrim,lpVertices,IdxOffset,
dwVertexBufferLen));
pdwIndexData = (DWORD *)lpPrim;
pContext->dwProvokingVertex = 0;
for( i = 0; i < dwPrimCount; i++ )
{
dwIndex0 = *pdwIndexData++;
dwIndex1 = *pdwIndexData++;
dwIndex2 = *pdwIndexData++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
RENDER_ONE_TRIANGLE(pContext,dwFillMode,pv);
}
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleList_MS_32IND,0);
} // _D3D_R3_DP2_IndexedTriangleList_MS_32IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleStrip_MS_32IND
//
// Render D3DDP2OP_INDEXEDTRIANGLESTRIP triangles
// Indices come as 32-bit entities ( DX7 only uses 16-bit indices)
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleStrip_MS_32IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i, *pdwIndexData;
D3DTLVERTEX *pv[4];
int vtx_a, vtx_b, bCulled;
DWORD dwFillMode = pContext->RenderStates[D3DRS_FILLMODE];
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleStrip_MS_32IND);
pdwIndexData = (DWORD *)lpPrim;
dwIndex0 = *pdwIndexData++;
dwIndex1 = *pdwIndexData++;
dwIndex2 = *pdwIndexData++;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->dwProvokingVertex = 0;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
INIT_RENDER_ONE_TRIANGLE(pContext,dwFillMode,pv,bCulled);
lpPrim += sizeof(WORD);
INIT_VERTEX_INDICES(pContext, vtx_a, vtx_b);
for( i = 1; i < dwPrimCount; i++ )
{
FLIP_CCW_CW_CULLING(pContext);
dwIndex2 = *pdwIndexData++;
pv[vtx_a] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
RENDER_ONE_TRIANGLE_CYCLE(pContext,
dwFillMode,
pv,
bCulled,
vtx_a);
CYCLE_VERTEX_INDICES(pContext, vtx_a, vtx_b);
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleStrip_MS_32IND,0);
} // _D3D_R3_DP2_IndexedTriangleStrip_MS_32IND
//-----------------------------------------------------------------------------
//
// _D3D_R3_DP2_IndexedTriangleFan_MS_32IND
//
// Render D3DDP2OP_INDEXEDTRIANGLEFAN triangles
// Indices come as 32-bit entities ( DX7 only uses 16-bit indices)
//
//-----------------------------------------------------------------------------
void
_D3D_R3_DP2_IndexedTriangleFan_MS_32IND(
P3_D3DCONTEXT *pContext,
DWORD dwPrimCount,
LPBYTE lpPrim,
LPD3DTLVERTEX lpVertices,
INT IdxOffset,
DWORD dwVertexBufferLen,
BOOL *pbError)
{
DWORD dwIndex0, dwIndex1, dwIndex2, i, *pdwIndexData;
D3DTLVERTEX *pv[4];
int vtx, lastVtx, bCulled;
DWORD dwFillMode = pContext->RenderStates[D3DRS_FILLMODE];
SAVE_CULLING_STATE(pContext);
DBG_ENTRY(_D3D_R3_DP2_IndexedTriangleFan_MS_32IND);
pdwIndexData = (DWORD *)lpPrim;
dwIndex0 = *pdwIndexData++;
dwIndex1 = *pdwIndexData++;
dwIndex2 = *pdwIndexData++;
lastVtx = vtx = 2;
pv[0] = LP_FVF_VERTEX(lpVertices, dwIndex0);
pv[1] = LP_FVF_VERTEX(lpVertices, dwIndex1);
pv[2] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex0);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex1);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, IdxOffset + dwIndex2);
pContext->dwProvokingVertex = 1;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
INIT_RENDER_ONE_TRIANGLE(pContext,dwFillMode,pv,bCulled);
lpPrim += sizeof(WORD);
for( i = 1; i < dwPrimCount; i++ )
{
// 2 -> 1, 1 -> 2
vtx ^= 3;
FLIP_CCW_CW_CULLING(pContext);
dwIndex2 = *pdwIndexData++;
pv[vtx] = LP_FVF_VERTEX(lpVertices, dwIndex2);
CHECK_DATABUF_LIMITS(pbError, dwVertexBufferLen, dwIndex2);
pContext->dwProvokingVertex = lastVtx;
pContext->pProvokingVertex = pv[pContext->dwProvokingVertex];
RENDER_ONE_TRIANGLE_CYCLE(pContext,
dwFillMode,
pv,
bCulled,
vtx);
lastVtx = vtx;
}
RESTORE_CULLING_STATE(pContext);
DBG_EXIT(_D3D_R3_DP2_IndexedTriangleFan_MS_32IND,0);
} // _D3D_R3_DP2_IndexedTriangleFan_MS_32IND
#endif // DX8_MULTSTREAMS
//-----------------------------------------------------------------------------
//
// _D3D_R3_PickVertexProcessor
//
// Pick appropriate triangle rendering functions based on texturing
//
//-----------------------------------------------------------------------------
void
_D3D_R3_PickVertexProcessor(
P3_D3DCONTEXT *pContext )
{
DWORD Flags = pContext->Flags;
DBG_ENTRY(_D3D_R3_PickVertexProcessor);
if (pContext->RenderStates[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME)
{
// Wireframe mode renderers
pContext->pRendTri_1V = __ProcessTri_1Vtx_Wire;
pContext->pRendTri_3V = __ProcessTri_3Vtx_Wire;
}
else if (pContext->RenderStates[D3DRENDERSTATE_FILLMODE] == D3DFILL_POINT)
{
#if DX8_DDI
if(IS_POINTSPRITE_ACTIVE(pContext))
{
// Point sprite mode renderers
pContext->pRendTri_1V = __ProcessTri_1Vtx_PointSprite;
pContext->pRendTri_3V = __ProcessTri_3Vtx_PointSprite;
}
else
#endif
{
// Point mode renderers
pContext->pRendTri_1V = __ProcessTri_1Vtx_Point;
pContext->pRendTri_3V = __ProcessTri_3Vtx_Point;
}
}
else
#if !defined(_WIN64)
// We avoid this path in IA64 as something is wrongly fed into the chip
if( ( Flags & SURFACE_PERSPCORRECT ) &&
( Flags & SURFACE_GOURAUD ) &&
(pContext->bTex0Valid) &&
(!pContext->bTex1Valid) )
{
// Solid mode renderes for single textured-gouraud shaded-persp corr
if(( pContext->RenderStates[D3DRENDERSTATE_WRAP0] )
|| ( pContext->RenderStates[D3DRENDERSTATE_WRAP1] ))
{
pContext->pRendTri_1V = __ProcessTri_1Vtx_Generic;
pContext->pRendTri_3V = __ProcessTri_3Vtx_Generic;
}
else
{
pContext->pRendTri_1V = __ProcessTri_1Vtx_PerspSingleTexGouraud;
pContext->pRendTri_3V = __ProcessTri_3Vtx_PerspSingleTexGouraud;
}
}
else
#endif !defined(_WIN64)
{
// Solid mode renderers for textured triangles
if( pContext->bTex0Valid || pContext->bTex1Valid )
{
pContext->pRendTri_1V = __ProcessTri_1Vtx_Generic;
pContext->pRendTri_3V = __ProcessTri_3Vtx_Generic;
}
else
{
// Solid mode renderers for non-textured triangles
pContext->pRendTri_1V = __ProcessTri_1Vtx_NoTexture;
pContext->pRendTri_3V = __ProcessTri_3Vtx_NoTexture;
}
}
DBG_EXIT(_D3D_R3_PickVertexProcessor,0);
} // _D3D_R3_PickVertexProcessor