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