1527 lines
54 KiB
C++
1527 lines
54 KiB
C++
//----------------------------------------------------------------------------
|
|
//
|
|
// dprim2.cpp
|
|
//
|
|
// Implements DrawPrimitives2.
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
//---------------------------------------------------------------------
|
|
// Entry is texture count. Clears all texture format bits in the FVF DWORD,
|
|
// that correspond to the texture count
|
|
// for this count
|
|
//---------------------------------------------------------------------
|
|
const DWORD g_TextureFormatMask[9] = {
|
|
~0x0000FFFF,
|
|
~0x0003FFFF,
|
|
~0x000FFFFF,
|
|
~0x003FFFFF,
|
|
~0x00FFFFFF,
|
|
~0x03FFFFFF,
|
|
~0x0FFFFFFF,
|
|
~0x3FFFFFFF,
|
|
~0xFFFFFFFF
|
|
};
|
|
|
|
HRESULT
|
|
RDFVFCheckAndStride( DWORD dwFVF, DWORD* pdwStride )
|
|
{
|
|
// If the runtime is DX8+, the dwFVF might be 0
|
|
// in which case the stride is obtained from the streams
|
|
if( dwFVF == 0 ) return S_OK;
|
|
|
|
DWORD dwTexCoord = FVF_TEXCOORD_NUMBER(dwFVF);
|
|
DWORD vertexType = dwFVF & D3DFVF_POSITION_MASK;
|
|
// Texture format bits above texture count should be zero
|
|
// Reserved field 0 and 2 should be 0
|
|
// Reserved 1 should be set only for LVERTEX
|
|
// Only two vertex position types allowed
|
|
if( dwFVF & g_TextureFormatMask[dwTexCoord] )
|
|
{
|
|
DPFERR( "FVF has incorrect texture format" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( dwFVF & (D3DFVF_RESERVED2 | D3DFVF_RESERVED0) )
|
|
{
|
|
DPFERR( "FVF has reserved bit(s) set" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( !(vertexType == D3DFVF_XYZRHW ||
|
|
vertexType == D3DFVF_XYZ ||
|
|
vertexType == D3DFVF_XYZB1 ||
|
|
vertexType == D3DFVF_XYZB2 ||
|
|
vertexType == D3DFVF_XYZB3 ||
|
|
vertexType == D3DFVF_XYZB4 ||
|
|
vertexType == D3DFVF_XYZB5) )
|
|
{
|
|
DPFERR( "FVF has incorrect position type" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( (vertexType == D3DFVF_XYZRHW) && (dwFVF & D3DFVF_NORMAL) )
|
|
{
|
|
DPFERR( "Normal should not be used with XYZRHW position type" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
*pdwStride = GetFVFVertexSize( dwFVF );
|
|
return D3D_OK;
|
|
}
|
|
|
|
|
|
inline D3DPRIMITIVETYPE ConvertDP2OPToPrimType(D3DHAL_DP2OPERATION Dp2Op)
|
|
{
|
|
switch (Dp2Op)
|
|
{
|
|
case D3DDP2OP_POINTS :
|
|
return D3DPT_POINTLIST;
|
|
case D3DDP2OP_INDEXEDLINELIST :
|
|
case D3DDP2OP_INDEXEDLINELIST2 :
|
|
case D3DDP2OP_LINELIST_IMM :
|
|
case D3DDP2OP_LINELIST :
|
|
return D3DPT_LINELIST;
|
|
case D3DDP2OP_TRIANGLELIST :
|
|
case D3DDP2OP_INDEXEDTRIANGLELIST :
|
|
case D3DDP2OP_INDEXEDTRIANGLELIST2:
|
|
return D3DPT_TRIANGLELIST;
|
|
case D3DDP2OP_LINESTRIP :
|
|
case D3DDP2OP_INDEXEDLINESTRIP :
|
|
return D3DPT_LINESTRIP;
|
|
case D3DDP2OP_TRIANGLESTRIP :
|
|
case D3DDP2OP_INDEXEDTRIANGLESTRIP:
|
|
return D3DPT_TRIANGLESTRIP;
|
|
case D3DDP2OP_TRIANGLEFAN :
|
|
case D3DDP2OP_INDEXEDTRIANGLEFAN :
|
|
case D3DDP2OP_TRIANGLEFAN_IMM :
|
|
return D3DPT_TRIANGLEFAN;
|
|
case D3DDP2OP_RENDERSTATE :
|
|
case D3DDP2OP_TEXTURESTAGESTATE :
|
|
case D3DDP2OP_VIEWPORTINFO :
|
|
case D3DDP2OP_WINFO :
|
|
default:
|
|
DPFM(4, DRV, ("(RefRast)Non primitive operation operation in DrawPrimitives2"));
|
|
return (D3DPRIMITIVETYPE)0;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// FvfToRDVertex
|
|
//
|
|
// Converts a series of FVF vertices to RDVertices, which are the internal
|
|
// currency of the RefDev.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
RefDev::FvfToRDVertex( PUINT8 pVtx, GArrayT<RDVertex>& dstArray, DWORD dwFvf,
|
|
DWORD dwStride, UINT cVertices )
|
|
{
|
|
for (DWORD i = 0; i < cVertices; i++)
|
|
{
|
|
dstArray[i].SetFvfData( (LPDWORD)pVtx, dwFvf );
|
|
pVtx += dwStride;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RefRastDrawPrimitives2
|
|
//
|
|
// This is called by D3DIM for API DrawPrimitives2 to draw a set of primitives
|
|
// using a vertex buffer.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD __stdcall
|
|
RefRastDrawPrimitives2(LPD3DHAL_DRAWPRIMITIVES2DATA pDPrim2Data)
|
|
{
|
|
HRESULT hr = D3D_OK;
|
|
|
|
RefDev *pRefDev;
|
|
DWORD dwStride = 0;
|
|
DWORD dwFVF = pDPrim2Data->dwVertexType;
|
|
PUINT8 pVtData = NULL;
|
|
PUINT8 pUMVtx = NULL;
|
|
DWORD dwNumVertices = pDPrim2Data->dwVertexLength;
|
|
|
|
VALIDATE_REFRAST_CONTEXT("RefRastDrawPrimitives", pDPrim2Data);
|
|
|
|
if( pDPrim2Data->lpVertices )
|
|
{
|
|
if (pDPrim2Data->dwFlags & D3DHALDP2_USERMEMVERTICES)
|
|
{
|
|
pUMVtx = (PUINT8)pDPrim2Data->lpVertices;
|
|
pVtData = pUMVtx + pDPrim2Data->dwVertexOffset;
|
|
}
|
|
else
|
|
{
|
|
pVtData = (PUINT8)pDPrim2Data->lpDDVertex->lpGbl->fpVidMem +
|
|
pDPrim2Data->dwVertexOffset;
|
|
}
|
|
}
|
|
|
|
LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)
|
|
((PUINT8)pDPrim2Data->lpDDCommands->lpGbl->fpVidMem +
|
|
pDPrim2Data->dwCommandOffset);
|
|
UINT_PTR CmdBoundary = (UINT_PTR)pCmd +
|
|
pDPrim2Data->dwCommandLength;
|
|
|
|
|
|
// Unconditionally get the vertex stride, since it can not change
|
|
if ((pDPrim2Data->ddrval = RDFVFCheckAndStride(
|
|
(DWORD)pDPrim2Data->dwVertexType, &dwStride)) != D3D_OK)
|
|
{
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
//
|
|
// If this is a pre-DX8 DDI, then the FVF shader needs to be set as
|
|
// the current shader. ONLY IF it requires vertex processing.
|
|
// Else, convert its data into the RDVertex array.
|
|
//
|
|
if( pRefDev->GetDDIType() < RDDDI_DX8HAL )
|
|
{
|
|
if( !FVF_TRANSFORMED( dwFVF ) )
|
|
{
|
|
BYTE CmdBytes[ sizeof( D3DHAL_DP2COMMAND ) +
|
|
sizeof( D3DHAL_DP2VERTEXSHADER ) ];
|
|
|
|
D3DHAL_DP2COMMAND& cmd = *(LPD3DHAL_DP2COMMAND)CmdBytes;
|
|
D3DHAL_DP2VERTEXSHADER& vs =
|
|
*(LPD3DHAL_DP2VERTEXSHADER)((LPD3DHAL_DP2COMMAND)CmdBytes + 1);
|
|
cmd.bCommand = D3DDP2OP_SETVERTEXSHADER;
|
|
cmd.wStateCount = 1;
|
|
vs.dwHandle = dwFVF;
|
|
pRefDev->Dp2SetVertexShader( (LPD3DHAL_DP2COMMAND)CmdBytes );
|
|
|
|
// Set the 0th stream here as well.
|
|
pRefDev->GetVStream( 0 ).m_pData = pVtData;
|
|
pRefDev->GetVStream( 0 ).m_dwStride = dwStride;
|
|
}
|
|
else
|
|
{
|
|
// Ask the RefDev to grow its TLVBuf Array and copy the
|
|
// FVF data into it.
|
|
HR_RET( pRefDev->GrowTLVArray( dwNumVertices ) );
|
|
pRefDev->FvfToRDVertex( pVtData, pRefDev->GetTLVArray(), dwFVF,
|
|
dwStride, dwNumVertices );
|
|
}
|
|
}
|
|
|
|
// Skip state check and texture lock if the first thing is state change
|
|
//
|
|
// WINFO is excluded here because it currently does not affect RGB/MMX
|
|
// and refrast does not care if it changes between begin/endrendering.
|
|
//
|
|
// VIEWPORTINFO is excluded here because it is OK to change the viewport
|
|
// between begin/endrendering on both RGB/MMX and Ref.
|
|
//
|
|
|
|
#ifndef __D3D_NULL_REF
|
|
// Loop through the data, update render states
|
|
// and then draw the primitive
|
|
for (;;)
|
|
{
|
|
LPDWORD lpdwRStates;
|
|
if (pDPrim2Data->dwFlags & D3DHALDP2_EXECUTEBUFFER)
|
|
lpdwRStates = pDPrim2Data->lpdwRStates;
|
|
else
|
|
lpdwRStates = NULL;
|
|
|
|
pDPrim2Data->ddrval = pRefDev->DrawPrimitives2( pUMVtx,
|
|
(UINT16)dwStride,
|
|
dwFVF,
|
|
dwNumVertices,
|
|
&pCmd,
|
|
lpdwRStates );
|
|
if (pDPrim2Data->ddrval != D3D_OK)
|
|
{
|
|
if (pDPrim2Data->ddrval == D3DERR_COMMAND_UNPARSED)
|
|
{
|
|
pDPrim2Data->dwErrorOffset = (UINT32)((ULONG_PTR)pCmd -
|
|
(UINT_PTR)(pDPrim2Data->lpDDCommands->lpGbl->fpVidMem));
|
|
}
|
|
goto EH_Exit;
|
|
}
|
|
if ((UINT_PTR)pCmd >= CmdBoundary)
|
|
break;
|
|
}
|
|
EH_Exit:
|
|
#else //__D3D_NULL_REF
|
|
pDPrim2Data->ddrval = S_OK;
|
|
#endif //__D3D_NULL_REF
|
|
|
|
|
|
hr = pRefDev->EndRendering();
|
|
|
|
if (pDPrim2Data->ddrval == D3D_OK)
|
|
{
|
|
pDPrim2Data->ddrval = hr;
|
|
}
|
|
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
#ifndef __D3D_NULL_REF
|
|
HRESULT FASTCALL
|
|
DoDrawIndexedTriList2( RefDev *pCtx,
|
|
WORD cPrims,
|
|
D3DHAL_DP2INDEXEDTRIANGLELIST *pTriList)
|
|
{
|
|
INT i;
|
|
D3DHAL_DP2INDEXEDTRIANGLELIST *pTri = pTriList;
|
|
GArrayT<RDVertex>& VtxArray = pCtx->GetTLVArray();
|
|
|
|
for (i = 0; i < cPrims; i ++)
|
|
{
|
|
HRESULT hr;
|
|
|
|
PUINT8 pVtx0, pVtx1, pVtx2;
|
|
RDVertex& Vtx0 = VtxArray[pTri->wV1];
|
|
RDVertex& Vtx1 = VtxArray[pTri->wV2];
|
|
RDVertex& Vtx2 = VtxArray[pTri->wV3];
|
|
pCtx->DrawTriangle( &Vtx0, &Vtx1, &Vtx2, pTri->wFlags);
|
|
pTri ++;
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// DoDrawPrimitives2
|
|
//
|
|
// It's called by RefRastDrawPrimitives2. .
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
RefDev::DrawPrimitives2( PUINT8 pUMVtx,
|
|
UINT16 dwStride,
|
|
DWORD dwFvf,
|
|
DWORD dwNumVertices,
|
|
LPD3DHAL_DP2COMMAND *ppCmd,
|
|
LPDWORD lpdwRStates )
|
|
{
|
|
LPD3DHAL_DP2COMMAND pCmd = *ppCmd;
|
|
HRESULT hr = S_OK;
|
|
|
|
DPFM(7, DRV, ("(RefRast)Read Ins: %08lx", *(LPDWORD)pCmd));
|
|
|
|
BOOL bWireframe =
|
|
(GetRS()[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME);
|
|
|
|
//
|
|
// Lock textures and setup the floating point state if the
|
|
// command is a drawing command, only if it has not been locked before
|
|
//
|
|
switch(pCmd->bCommand)
|
|
{
|
|
case D3DDP2OP_POINTS:
|
|
case D3DDP2OP_LINELIST:
|
|
case D3DDP2OP_LINESTRIP:
|
|
case D3DDP2OP_TRIANGLELIST:
|
|
case D3DDP2OP_TRIANGLESTRIP:
|
|
case D3DDP2OP_TRIANGLEFAN:
|
|
case D3DDP2OP_INDEXEDLINELIST:
|
|
case D3DDP2OP_INDEXEDLINELIST2:
|
|
case D3DDP2OP_INDEXEDLINESTRIP:
|
|
case D3DDP2OP_INDEXEDTRIANGLELIST:
|
|
case D3DDP2OP_INDEXEDTRIANGLELIST2:
|
|
case D3DDP2OP_INDEXEDTRIANGLESTRIP:
|
|
case D3DDP2OP_INDEXEDTRIANGLEFAN:
|
|
case D3DDP2OP_TRIANGLEFAN_IMM:
|
|
case D3DDP2OP_LINELIST_IMM:
|
|
_ASSERT( GetDDIType() < RDDDI_DX8HAL, "Older drawing tokens"
|
|
" received for DX8+ DDI" );
|
|
// Fall through
|
|
case D3DDP2OP_DRAWPRIMITIVE:
|
|
case D3DDP2OP_DRAWINDEXEDPRIMITIVE:
|
|
case D3DDP2OP_CLIPPEDTRIANGLEFAN:
|
|
case D3DDP2OP_DRAWPRIMITIVE2:
|
|
case D3DDP2OP_DRAWINDEXEDPRIMITIVE2:
|
|
case D3DDP2OP_DRAWRECTPATCH:
|
|
case D3DDP2OP_DRAWTRIPATCH:
|
|
// Turn off the TCI override, this will be set if needed later
|
|
// on during vertex processing by the fixed function pipeline.
|
|
m_bOverrideTCI = FALSE;
|
|
// This stuff needs to be updated only on pre DX7 drivers.
|
|
HR_RET(RefRastUpdatePalettes( this ));
|
|
HR_RET(BeginRendering());
|
|
}
|
|
|
|
switch(pCmd->bCommand)
|
|
{
|
|
case D3DDP2OP_STATESET:
|
|
{
|
|
LPD3DHAL_DP2STATESET pStateSetOp =
|
|
(LPD3DHAL_DP2STATESET)(pCmd + 1);
|
|
|
|
switch (pStateSetOp->dwOperation)
|
|
{
|
|
case D3DHAL_STATESETBEGIN :
|
|
HR_RET(BeginStateSet(pStateSetOp->dwParam));
|
|
break;
|
|
case D3DHAL_STATESETEND :
|
|
HR_RET(EndStateSet());
|
|
break;
|
|
case D3DHAL_STATESETDELETE :
|
|
HR_RET(DeleteStateSet(pStateSetOp->dwParam));
|
|
break;
|
|
case D3DHAL_STATESETEXECUTE:
|
|
HR_RET(ExecuteStateSet(pStateSetOp->dwParam));
|
|
break;
|
|
case D3DHAL_STATESETCAPTURE:
|
|
HR_RET(CaptureStateSet(pStateSetOp->dwParam));
|
|
break;
|
|
case D3DHAL_STATESETCREATE:
|
|
HR_RET(CreateStateSet(pStateSetOp->dwParam,
|
|
pStateSetOp->sbType));
|
|
break;
|
|
default :
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)(pStateSetOp + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_VIEWPORTINFO:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetViewport(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2VIEWPORTINFO *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_WINFO:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetWRange(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2WINFO *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_RENDERSTATE:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetRenderStates(this, dwFvf, pCmd,
|
|
lpdwRStates));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2RENDERSTATE *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_TEXTURESTAGESTATE:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2TextureStageState(this, dwFvf,
|
|
pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((LPD3DHAL_DP2TEXTURESTAGESTATE)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
// This is a special case because it has edge flags. Other D3DDP2OP
|
|
// can actually make use of DrawOneIndexedPrimitive/DrawOnePrimitive.
|
|
case D3DDP2OP_INDEXEDTRIANGLELIST:
|
|
{
|
|
// This command is used in execute buffers. So untransformed
|
|
// vertices are not expected by this refrast.
|
|
_ASSERT( FVF_TRANSFORMED(dwFvf), "Untransformed vertices in "
|
|
"D3DDP2OP_INDEXEDTRIANGLELIST" );
|
|
|
|
WORD cPrims = pCmd->wPrimitiveCount;
|
|
HR_RET(DoDrawIndexedTriList2(
|
|
this, cPrims, (D3DHAL_DP2INDEXEDTRIANGLELIST *)(pCmd + 1)));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
|
|
sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST) * cPrims);
|
|
}
|
|
break;
|
|
case D3DDP2OP_INDEXEDLINELIST:
|
|
{
|
|
// This command is used in execute buffers. So untransformed
|
|
// vertices are not expected by this refrast.
|
|
_ASSERT( FVF_TRANSFORMED(dwFvf),
|
|
"Untransformed vertices in D3DDP2OP_INDEXEDLINELIST" );
|
|
|
|
HR_RET(DrawOneIndexedPrimitive( GetTLVArray(),
|
|
0,
|
|
(LPWORD)(pCmd + 1),
|
|
0,
|
|
pCmd->wPrimitiveCount * 2,
|
|
D3DPT_LINELIST));
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
|
|
pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
|
|
}
|
|
break;
|
|
// Following ops All use DrawOneIndexedPrimitive/DrawOnePrimitive.
|
|
// There are some extra overheads introduced because those two functions
|
|
// need to switch over the PrimTypes while we already know it here.
|
|
// Striping out the code to add inline functions for each PrimType means
|
|
// adding about twenty functions(considering the types of prim times types
|
|
// of vertex). So I have used DrawOneIndexedPrimitive/DrawOnePrimitive
|
|
// here anyway. We can later change it if necessary.
|
|
case D3DDP2OP_POINTS:
|
|
{
|
|
WORD cPrims = pCmd->wPrimitiveCount;
|
|
D3DHAL_DP2POINTS *pPt = (D3DHAL_DP2POINTS *)(pCmd + 1);
|
|
WORD i;
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
for (i = 0; i < cPrims; i++)
|
|
{
|
|
HR_RET(ProcessPrimitive( D3DPT_POINTLIST,
|
|
pPt->wVStart,
|
|
pPt->wCount,
|
|
0, 0 ));
|
|
pPt ++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
for (i = 0; i < cPrims; i++)
|
|
{
|
|
HR_RET(m_Clipper.DrawOnePrimitive( GetTLVArray(),
|
|
pPt->wVStart,
|
|
D3DPT_POINTLIST,
|
|
pPt->wCount));
|
|
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
pPt ++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < cPrims; i++)
|
|
{
|
|
HR_RET(DrawOnePrimitive( GetTLVArray(),
|
|
pPt->wVStart,
|
|
D3DPT_POINTLIST,
|
|
pPt->wCount));
|
|
pPt ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pPt;
|
|
}
|
|
break;
|
|
case D3DDP2OP_LINELIST:
|
|
{
|
|
D3DHAL_DP2LINELIST *pLine = (D3DHAL_DP2LINELIST *)(pCmd + 1);
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive( D3DPT_LINELIST, pLine->wVStart,
|
|
pCmd->wPrimitiveCount * 2, 0, 0 ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pLine->wVStart,
|
|
D3DPT_LINELIST,
|
|
pCmd->wPrimitiveCount * 2));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pLine->wVStart,
|
|
D3DPT_LINELIST,
|
|
pCmd->wPrimitiveCount * 2));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
|
|
}
|
|
break;
|
|
case D3DDP2OP_INDEXEDLINELIST2:
|
|
{
|
|
DWORD dwNumIndices = pCmd->wPrimitiveCount*2;
|
|
LPD3DHAL_DP2STARTVERTEX lpStartVertex =
|
|
(LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
|
|
|
|
// Set the Index Stream
|
|
m_IndexStream.m_pData = (LPBYTE)(lpStartVertex + 1);
|
|
m_IndexStream.m_dwStride = 2;
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive(
|
|
D3DPT_LINELIST,
|
|
lpStartVertex->wVStart,
|
|
dwNumVertices-lpStartVertex->wVStart,
|
|
0,
|
|
dwNumIndices ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_LINELIST));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_LINELIST));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
|
|
pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
|
|
}
|
|
break;
|
|
case D3DDP2OP_LINESTRIP:
|
|
{
|
|
D3DHAL_DP2LINESTRIP *pLine = (D3DHAL_DP2LINESTRIP *)(pCmd + 1);
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive( D3DPT_LINESTRIP,
|
|
pLine->wVStart,
|
|
pCmd->wPrimitiveCount + 1,
|
|
0, 0 ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pLine->wVStart,
|
|
D3DPT_LINESTRIP,
|
|
pCmd->wPrimitiveCount + 1));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pLine->wVStart,
|
|
D3DPT_LINESTRIP,
|
|
pCmd->wPrimitiveCount + 1));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
|
|
}
|
|
break;
|
|
case D3DDP2OP_INDEXEDLINESTRIP:
|
|
{
|
|
DWORD dwNumIndices = pCmd->wPrimitiveCount + 1;
|
|
LPD3DHAL_DP2STARTVERTEX lpStartVertex =
|
|
(LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
|
|
|
|
// Set the Index Stream
|
|
m_IndexStream.m_pData = (LPBYTE)(lpStartVertex + 1);
|
|
m_IndexStream.m_dwStride = 2;
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive(
|
|
D3DPT_LINESTRIP,
|
|
lpStartVertex->wVStart,
|
|
dwNumVertices-lpStartVertex->wVStart,
|
|
0,
|
|
dwNumIndices ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_LINESTRIP));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_LINESTRIP));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
|
|
dwNumIndices * sizeof(WORD));
|
|
}
|
|
break;
|
|
case D3DDP2OP_TRIANGLELIST:
|
|
{
|
|
D3DHAL_DP2TRIANGLELIST *pTri = (D3DHAL_DP2TRIANGLELIST *)(pCmd + 1);
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive( D3DPT_TRIANGLELIST,
|
|
pTri->wVStart,
|
|
pCmd->wPrimitiveCount * 3,
|
|
0, 0 ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pTri->wVStart,
|
|
D3DPT_TRIANGLELIST,
|
|
pCmd->wPrimitiveCount * 3));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOnePrimitive( GetTLVArray(),
|
|
pTri->wVStart,
|
|
D3DPT_TRIANGLELIST,
|
|
pCmd->wPrimitiveCount * 3));
|
|
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
|
|
}
|
|
break;
|
|
case D3DDP2OP_INDEXEDTRIANGLELIST2:
|
|
{
|
|
DWORD dwNumIndices = pCmd->wPrimitiveCount*3;
|
|
LPD3DHAL_DP2STARTVERTEX lpStartVertex =
|
|
(LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
|
|
|
|
// Set the Index Stream
|
|
m_IndexStream.m_pData = (LPBYTE)(lpStartVertex + 1);
|
|
m_IndexStream.m_dwStride = 2;
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive(
|
|
D3DPT_TRIANGLELIST,
|
|
lpStartVertex->wVStart,
|
|
dwNumVertices-lpStartVertex->wVStart,
|
|
0,
|
|
dwNumIndices));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_TRIANGLELIST));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_TRIANGLELIST));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
|
|
dwNumIndices * sizeof(WORD));
|
|
}
|
|
break;
|
|
case D3DDP2OP_TRIANGLESTRIP:
|
|
{
|
|
D3DHAL_DP2TRIANGLESTRIP *pTri = (D3DHAL_DP2TRIANGLESTRIP *)(pCmd + 1);
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive( D3DPT_TRIANGLESTRIP,
|
|
pTri->wVStart,
|
|
pCmd->wPrimitiveCount + 2,
|
|
0, 0 ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pTri->wVStart,
|
|
D3DPT_TRIANGLESTRIP,
|
|
pCmd->wPrimitiveCount + 2));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pTri->wVStart,
|
|
D3DPT_TRIANGLESTRIP,
|
|
pCmd->wPrimitiveCount + 2));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
|
|
}
|
|
break;
|
|
case D3DDP2OP_INDEXEDTRIANGLESTRIP:
|
|
{
|
|
DWORD dwNumIndices = pCmd->wPrimitiveCount+2;
|
|
LPD3DHAL_DP2STARTVERTEX lpStartVertex =
|
|
(LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
|
|
|
|
// Set the Index Stream
|
|
m_IndexStream.m_pData = (LPBYTE)(lpStartVertex + 1);
|
|
m_IndexStream.m_dwStride = 2;
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive(
|
|
D3DPT_TRIANGLESTRIP,
|
|
lpStartVertex->wVStart,
|
|
dwNumVertices-lpStartVertex->wVStart,
|
|
0,
|
|
dwNumIndices ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_TRIANGLESTRIP));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_TRIANGLESTRIP));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
|
|
dwNumIndices * sizeof(WORD));
|
|
}
|
|
break;
|
|
case D3DDP2OP_TRIANGLEFAN:
|
|
{
|
|
D3DHAL_DP2TRIANGLEFAN *pTri = (D3DHAL_DP2TRIANGLEFAN *)(pCmd + 1);
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive( D3DPT_TRIANGLEFAN,
|
|
pTri->wVStart,
|
|
pCmd->wPrimitiveCount + 2,
|
|
0, 0 ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pTri->wVStart,
|
|
D3DPT_TRIANGLEFAN,
|
|
pCmd->wPrimitiveCount + 2));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOnePrimitive(
|
|
GetTLVArray(),
|
|
pTri->wVStart,
|
|
D3DPT_TRIANGLEFAN,
|
|
pCmd->wPrimitiveCount + 2));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
|
|
}
|
|
break;
|
|
case D3DDP2OP_INDEXEDTRIANGLEFAN:
|
|
{
|
|
DWORD dwNumIndices = pCmd->wPrimitiveCount + 2;
|
|
LPD3DHAL_DP2STARTVERTEX lpStartVertex =
|
|
(LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
|
|
|
|
// Set the Index Stream
|
|
m_IndexStream.m_pData = (LPBYTE)(lpStartVertex + 1);
|
|
m_IndexStream.m_dwStride = 2;
|
|
|
|
// Check if the primitive is transformed or not
|
|
if (!FVF_TRANSFORMED(dwFvf))
|
|
{
|
|
HR_RET(ProcessPrimitive(
|
|
D3DPT_TRIANGLEFAN,
|
|
lpStartVertex->wVStart,
|
|
dwNumVertices-lpStartVertex->wVStart,
|
|
0,
|
|
dwNumIndices ));
|
|
}
|
|
else
|
|
{
|
|
if( GetRS()[D3DRENDERSTATE_CLIPPING] )
|
|
{
|
|
HR_RET( UpdateClipper() );
|
|
HR_RET(m_Clipper.DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_TRIANGLEFAN));
|
|
// Clean up the FVFP_CLIP bit for the
|
|
// copied vertices.
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOneIndexedPrimitive(
|
|
GetTLVArray(),
|
|
lpStartVertex->wVStart,
|
|
(LPWORD)(lpStartVertex + 1),
|
|
0,
|
|
dwNumIndices,
|
|
D3DPT_TRIANGLEFAN));
|
|
}
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
|
|
dwNumIndices * sizeof(WORD));
|
|
}
|
|
break;
|
|
case D3DDP2OP_TRIANGLEFAN_IMM:
|
|
{
|
|
DWORD vertexCount = pCmd->wPrimitiveCount + 2;
|
|
// Make sure the pFanVtx pointer is DWORD aligned: (pFanVtx +3) % 4
|
|
PUINT8 pFanVtx = (PUINT8)
|
|
(((ULONG_PTR)(pCmd + 1) +
|
|
sizeof(D3DHAL_DP2TRIANGLEFAN_IMM) + 3) & ~3);
|
|
|
|
// Assert here. This case should never be reached.
|
|
// This command is used by front end to give clipped
|
|
// primitives inside the command itself. Since TL Hals
|
|
// do their own clipping untransformed vertices but yet
|
|
// clipped are not expected here.
|
|
// Assert that only transformed vertices can reach here
|
|
_ASSERT( FVF_TRANSFORMED(dwFvf),
|
|
"Untransformed vertices in D3DDP2OP_TRIANGLEFAN_IMM" );
|
|
|
|
GArrayT<RDVertex> ClipVtxArray;
|
|
HR_RET(ClipVtxArray.Grow( vertexCount ) );
|
|
FvfToRDVertex( pFanVtx, ClipVtxArray, dwFvf, dwStride,
|
|
vertexCount );
|
|
if (bWireframe)
|
|
{
|
|
// Read edge flags
|
|
UINT32 dwEdgeFlags =
|
|
((LPD3DHAL_DP2TRIANGLEFAN_IMM)(pCmd + 1))->dwEdgeFlags;
|
|
HR_RET(DrawOneEdgeFlagTriangleFan( ClipVtxArray,
|
|
vertexCount,
|
|
dwEdgeFlags));
|
|
}
|
|
else
|
|
{
|
|
HR_RET(DrawOnePrimitive( ClipVtxArray,
|
|
0,
|
|
D3DPT_TRIANGLEFAN,
|
|
vertexCount));
|
|
}
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pFanVtx +
|
|
vertexCount * dwStride);
|
|
}
|
|
break;
|
|
case D3DDP2OP_LINELIST_IMM:
|
|
{
|
|
DWORD vertexCount = pCmd->wPrimitiveCount * 2;
|
|
// Make sure the pLineVtx pointer is DWORD aligned:
|
|
// (pLineVtx +3) % 4
|
|
PUINT8 pLineVtx = (PUINT8)(((ULONG_PTR)(pCmd + 1) + 3) & ~3);
|
|
|
|
// Assert here. This case should never be reached.
|
|
// This command is used by front end to give clipped
|
|
// primitives inside the command itself. Since TL Hals
|
|
// do their own clipping untransformed vertices but yet
|
|
// clipped are not expected here.
|
|
// Assert that only transformed vertices can reach here
|
|
_ASSERT( FVF_TRANSFORMED(dwFvf),
|
|
"Untransformed vertices in D3DDP2OP_LINELIST_IMM" );
|
|
|
|
GArrayT<RDVertex> ClipVtxArray;
|
|
HR_RET(ClipVtxArray.Grow( vertexCount ) );
|
|
FvfToRDVertex( pLineVtx, ClipVtxArray, dwFvf, dwStride,
|
|
vertexCount );
|
|
HR_RET(DrawOnePrimitive( ClipVtxArray,
|
|
0,
|
|
D3DPT_LINELIST,
|
|
vertexCount));
|
|
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pLineVtx +
|
|
vertexCount * dwStride);
|
|
}
|
|
break;
|
|
case D3DDP2OP_DRAWPRIMITIVE:
|
|
{
|
|
HR_RET(Dp2DrawPrimitive(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2DRAWPRIMITIVE *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_DRAWPRIMITIVE2:
|
|
{
|
|
HR_RET(Dp2DrawPrimitive2(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2DRAWPRIMITIVE2 *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_DRAWRECTPATCH:
|
|
{
|
|
LPD3DHAL_DP2DRAWRECTPATCH pDP =
|
|
(LPD3DHAL_DP2DRAWRECTPATCH)(pCmd + 1);
|
|
for( int i = 0; i < pCmd->wStateCount; i++ )
|
|
{
|
|
HR_RET(DrawRectPatch(pDP));
|
|
bool hassegs = (pDP->Flags & RTPATCHFLAG_HASSEGS) != 0;
|
|
bool hasinfo = (pDP->Flags & RTPATCHFLAG_HASINFO) != 0;
|
|
if(hassegs)
|
|
{
|
|
pDP = (LPD3DHAL_DP2DRAWRECTPATCH)((BYTE*)(pDP + 1) +
|
|
sizeof(FLOAT) * 4);
|
|
}
|
|
else
|
|
{
|
|
++pDP;
|
|
}
|
|
if(hasinfo)
|
|
{
|
|
pDP = (LPD3DHAL_DP2DRAWRECTPATCH)((BYTE*)pDP + sizeof(D3DRECTPATCH_INFO));
|
|
}
|
|
}
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pDP;
|
|
}
|
|
break;
|
|
case D3DDP2OP_DRAWTRIPATCH:
|
|
{
|
|
LPD3DHAL_DP2DRAWTRIPATCH pDP =
|
|
(LPD3DHAL_DP2DRAWTRIPATCH)(pCmd + 1);
|
|
for( int i = 0; i < pCmd->wStateCount; i++ )
|
|
{
|
|
HR_RET(DrawTriPatch(pDP));
|
|
bool hassegs = (pDP->Flags & RTPATCHFLAG_HASSEGS) != 0;
|
|
bool hasinfo = (pDP->Flags & RTPATCHFLAG_HASINFO) != 0;
|
|
if(hassegs)
|
|
{
|
|
pDP = (LPD3DHAL_DP2DRAWTRIPATCH)((BYTE*)(pDP + 1) +
|
|
sizeof(FLOAT) * 3);
|
|
}
|
|
else
|
|
{
|
|
++pDP;
|
|
}
|
|
if(hasinfo)
|
|
{
|
|
pDP = (LPD3DHAL_DP2DRAWTRIPATCH)((BYTE*)pDP + sizeof(D3DTRIPATCH_INFO));
|
|
}
|
|
}
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pDP;
|
|
}
|
|
break;
|
|
case D3DDP2OP_DRAWINDEXEDPRIMITIVE:
|
|
{
|
|
HR_RET(Dp2DrawIndexedPrimitive(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2DRAWINDEXEDPRIMITIVE *)(pCmd + 1) +
|
|
pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_DRAWINDEXEDPRIMITIVE2:
|
|
{
|
|
HR_RET(Dp2DrawIndexedPrimitive2(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2DRAWINDEXEDPRIMITIVE2 *)(pCmd + 1) +
|
|
pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_CLIPPEDTRIANGLEFAN:
|
|
{
|
|
HR_RET(Dp2DrawClippedTriFan(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_CLIPPEDTRIANGLEFAN*)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_ZRANGE:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetZRange(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2ZRANGE *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_SETMATERIAL:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetMaterial(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETMATERIAL *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_SETLIGHT:
|
|
{
|
|
DWORD dwSLStride = 0;
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetLight(this, pCmd, &dwSLStride));
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)pCmd + dwSLStride);
|
|
}
|
|
break;
|
|
case D3DDP2OP_CREATELIGHT:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2CreateLight(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2CREATELIGHT *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_SETTRANSFORM:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetTransform(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETTRANSFORM *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_MULTIPLYTRANSFORM:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2MultiplyTransform(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2MULTIPLYTRANSFORM *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_EXT:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetExtention(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2EXT *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_SETRENDERTARGET:
|
|
{
|
|
HR_RET(Dp2SetRenderTarget(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETRENDERTARGET*)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DDP2OP_CLEAR:
|
|
{
|
|
HR_RET(Clear(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pCmd + 1) +
|
|
sizeof(D3DHAL_DP2CLEAR) + (pCmd->wStateCount - 1) * sizeof(RECT));
|
|
}
|
|
break;
|
|
case D3DDP2OP_SETCLIPPLANE:
|
|
{
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetClipPlane(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETCLIPPLANE *)(pCmd + 1) + pCmd->wStateCount);
|
|
}
|
|
break;
|
|
case D3DOP_SPAN:
|
|
// Skip over
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pCmd + 1) +
|
|
pCmd->wPrimitiveCount * pCmd->bReserved );
|
|
break;
|
|
case D3DDP2OP_CREATEVERTEXSHADER:
|
|
{
|
|
LPD3DHAL_DP2CREATEVERTEXSHADER pCVS =
|
|
(LPD3DHAL_DP2CREATEVERTEXSHADER)(pCmd + 1);
|
|
WORD i;
|
|
|
|
for( i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
LPDWORD pDecl = (LPDWORD)(pCVS + 1);
|
|
LPDWORD pCode = (LPDWORD)((LPBYTE)pDecl + pCVS->dwDeclSize);
|
|
hr = Dp2CreateVertexShader( pCVS->dwHandle,
|
|
pCVS->dwDeclSize, pDecl,
|
|
pCVS->dwCodeSize, pCode );
|
|
if( FAILED( hr ) ) break;
|
|
// Update the pointer
|
|
pCVS = (LPD3DHAL_DP2CREATEVERTEXSHADER)((LPBYTE)pCode +
|
|
pCVS->dwCodeSize);
|
|
}
|
|
// Successful termination of the loop:
|
|
// Update the command buffer pointer
|
|
if( i == pCmd->wStateCount )
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pCVS;
|
|
else
|
|
return hr;
|
|
break;
|
|
}
|
|
case D3DDP2OP_DELETEVERTEXSHADER:
|
|
HR_RET(Dp2DeleteVertexShader(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2VERTEXSHADER *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
case D3DDP2OP_SETVERTEXSHADER:
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetVertexShader(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2VERTEXSHADER *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
case D3DDP2OP_SETVERTEXSHADERCONST:
|
|
{
|
|
LPD3DHAL_DP2SETVERTEXSHADERCONST pSVC =
|
|
(LPD3DHAL_DP2SETVERTEXSHADERCONST)(pCmd + 1);
|
|
WORD i;
|
|
for( i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
LPDWORD pData = (LPDWORD)(pSVC + 1);
|
|
hr = pStateSetFuncTbl->pfnDp2SetVertexShaderConsts(
|
|
this, pSVC->dwRegister, pSVC->dwCount, pData );
|
|
if( FAILED( hr ) ) break;
|
|
// Update the pointer
|
|
pSVC = (LPD3DHAL_DP2SETVERTEXSHADERCONST)((LPBYTE)pData +
|
|
pSVC->dwCount * 4 *
|
|
sizeof( float ) );
|
|
}
|
|
|
|
// Successful termination of the loop:
|
|
// Update the command buffer pointer
|
|
if( i == pCmd->wStateCount )
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pSVC;
|
|
else
|
|
return hr;
|
|
break;
|
|
}
|
|
case D3DDP2OP_SETSTREAMSOURCE:
|
|
// This function also updates the ppCmd pointer
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetStreamSource(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETSTREAMSOURCE *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
case D3DDP2OP_SETSTREAMSOURCEUM:
|
|
// This function also updates the ppCmd pointer
|
|
HR_RET(Dp2SetStreamSourceUM( pCmd, pUMVtx ));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETSTREAMSOURCEUM *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
case D3DDP2OP_SETINDICES:
|
|
// This function also updates the ppCmd pointer
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetIndices(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETINDICES *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
case D3DDP2OP_CREATEPIXELSHADER:
|
|
{
|
|
LPD3DHAL_DP2CREATEPIXELSHADER pCPS =
|
|
(LPD3DHAL_DP2CREATEPIXELSHADER)(pCmd + 1);
|
|
WORD i;
|
|
|
|
for( i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
LPDWORD pCode = (LPDWORD)(pCPS + 1);
|
|
hr = Dp2CreatePixelShader( pCPS->dwHandle,
|
|
pCPS->dwCodeSize, pCode );
|
|
if( FAILED( hr ) ) break;
|
|
// Update the pointer
|
|
pCPS = (LPD3DHAL_DP2CREATEPIXELSHADER)((LPBYTE)pCode +
|
|
pCPS->dwCodeSize);
|
|
}
|
|
// Successful termination of the loop:
|
|
// Update the command buffer pointer
|
|
if( i == pCmd->wStateCount )
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pCPS;
|
|
else
|
|
return hr;
|
|
break;
|
|
}
|
|
case D3DDP2OP_DELETEPIXELSHADER:
|
|
HR_RET(Dp2DeletePixelShader(pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2PIXELSHADER *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
case D3DDP2OP_SETPIXELSHADER:
|
|
HR_RET(pStateSetFuncTbl->pfnDp2SetPixelShader(this, pCmd));
|
|
// Update the command buffer pointer
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2PIXELSHADER *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
case D3DDP2OP_SETPIXELSHADERCONST:
|
|
{
|
|
LPD3DHAL_DP2SETPIXELSHADERCONST pSVC =
|
|
(LPD3DHAL_DP2SETPIXELSHADERCONST)(pCmd + 1);
|
|
WORD i;
|
|
for( i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
LPDWORD pData = (LPDWORD)(pSVC + 1);
|
|
hr = pStateSetFuncTbl->pfnDp2SetPixelShaderConsts(
|
|
this, pSVC->dwRegister, pSVC->dwCount, pData );
|
|
if( FAILED( hr ) ) break;
|
|
// Update the pointer
|
|
pSVC = (LPD3DHAL_DP2SETPIXELSHADERCONST)((LPBYTE)pData +
|
|
pSVC->dwCount * 4 *
|
|
sizeof( float ) );
|
|
}
|
|
|
|
// Successful termination of the loop:
|
|
// Update the command buffer pointer
|
|
if( i == pCmd->wStateCount )
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pSVC;
|
|
else
|
|
return hr;
|
|
break;
|
|
}
|
|
case D3DDP2OP_SETPALETTE:
|
|
{
|
|
HR_RET(Dp2SetPalette(pCmd));
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETPALETTE *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
}
|
|
case D3DDP2OP_UPDATEPALETTE:
|
|
{
|
|
LPD3DHAL_DP2UPDATEPALETTE pUP = (LPD3DHAL_DP2UPDATEPALETTE)(pCmd + 1);
|
|
WORD i;
|
|
for( i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
PALETTEENTRY* pEntries = (PALETTEENTRY *)(pUP + 1);
|
|
HR_RET(Dp2UpdatePalette(pUP, pEntries));
|
|
pUP = (LPD3DHAL_DP2UPDATEPALETTE)(pEntries + pUP->wNumEntries);
|
|
}
|
|
if( i == pCmd->wStateCount )
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pUP;
|
|
else
|
|
return hr;
|
|
break;
|
|
}
|
|
case D3DDP2OP_SETTEXLOD:
|
|
{
|
|
HR_RET(Dp2SetTexLod(pCmd));
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETTEXLOD *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
}
|
|
case D3DDP2OP_SETPRIORITY:
|
|
{
|
|
// Skip these tokens. RefDev doesnt need to handle SetPriority
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)
|
|
((D3DHAL_DP2SETPRIORITY *)(pCmd + 1) + pCmd->wStateCount);
|
|
break;
|
|
}
|
|
case D3DDP2OP_TEXBLT:
|
|
{
|
|
LPD3DHAL_DP2TEXBLT pTB = (LPD3DHAL_DP2TEXBLT)(pCmd + 1);
|
|
for( WORD i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
if( pTB->dwDDDestSurface == 0 )
|
|
{
|
|
// This is a PreLoad command, ignore it since
|
|
// RefDev just fakes driver management.
|
|
}
|
|
else
|
|
{
|
|
DPFERR( "TEXBLT not supported by RefDev\n" );
|
|
}
|
|
pTB++;
|
|
}
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pTB;
|
|
break;
|
|
}
|
|
case D3DDP2OP_BUFFERBLT:
|
|
{
|
|
LPD3DHAL_DP2BUFFERBLT pBB = (LPD3DHAL_DP2BUFFERBLT)(pCmd + 1);
|
|
for( WORD i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
if( pBB->dwDDDestSurface == 0 )
|
|
{
|
|
// This is a PreLoad command, ignore it since
|
|
// RefDev just fakes driver management.
|
|
}
|
|
else
|
|
{
|
|
DPFERR( "BUFFERBLT not supported by RefDev\n" );
|
|
}
|
|
pBB++;
|
|
}
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pBB;
|
|
break;
|
|
}
|
|
case D3DDP2OP_VOLUMEBLT:
|
|
{
|
|
LPD3DHAL_DP2VOLUMEBLT pVB = (LPD3DHAL_DP2VOLUMEBLT)(pCmd + 1);
|
|
for( WORD i = 0; i < pCmd->wStateCount ; i++ )
|
|
{
|
|
if( pVB->dwDDDestSurface == 0 )
|
|
{
|
|
// This is a PreLoad command, ignore it since
|
|
// RefDev just fakes driver management.
|
|
}
|
|
else
|
|
{
|
|
DPFERR( "VOLUMEBLT not supported by RefDev\n" );
|
|
}
|
|
pVB++;
|
|
}
|
|
*ppCmd = (LPD3DHAL_DP2COMMAND)pVB;
|
|
break;
|
|
}
|
|
case D3DOP_MATRIXLOAD:
|
|
{
|
|
DPFERR( "MATRIXLOAD not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_MATRIXMULTIPLY:
|
|
{
|
|
DPFERR( "MATRIXMULTIPLY not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_STATETRANSFORM:
|
|
{
|
|
DPFERR( "STATETRANSFORM not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_STATELIGHT:
|
|
{
|
|
DPFERR( "STATELIGHT not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_TEXTURELOAD:
|
|
{
|
|
DPFERR( "TEXTURELOAD not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_BRANCHFORWARD:
|
|
{
|
|
DPFERR( "BRANCHFORWARD not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_SETSTATUS:
|
|
{
|
|
DPFERR( "SETSTATUS not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_EXIT:
|
|
{
|
|
DPFERR( "EXIT not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
case D3DOP_PROCESSVERTICES:
|
|
{
|
|
DPFERR( "PROCESSVERTICES not supported by RefDev\n" );
|
|
hr = D3DERR_COMMAND_UNPARSED;
|
|
break;
|
|
}
|
|
default:
|
|
DPFERR( "Unknown command encountered" );
|
|
return E_FAIL;
|
|
}
|
|
return hr;
|
|
}
|
|
#endif //__D3D_NULL_REF
|