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

539 lines
22 KiB

//----------------------------------------------------------------------------
//
// dprim2.cpp
//
// Implements DrawPrimitives2.
//
// Copyright (C) Microsoft Corporation, 1997.
//
//----------------------------------------------------------------------------
include(`m4hdr.mh')dnl
#include "pch.cpp"
#pragma hdrstop
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:
D3D_INFO(4, "(Rast)Non primitive operation operation in DrawPrimitives2");
return (D3DPRIMITIVETYPE)0;
}
}
define(`d_DrawPrim2', `
//----------------------------------------------------------------------------
//
// $1DrawPrimitives2
//
// This is called by D3DIM for API DrawPrimitives2 to draw a set of primitives
// using a vertex buffer.
//
//----------------------------------------------------------------------------
DWORD __stdcall
$1DrawPrimitives2(LPD3DHAL_DRAWPRIMITIVES2DATA pDPrim2Data)
{
HRESULT hr;
ifelse(`$1', `Rast',`
D3DContext *pDCtx;', `
ReferenceRasterizer *pRefRast;
DWORD dwStride;')
PUINT8 pVtData;
ifelse(`$1', `Rast',`
VALIDATE_D3DCONTEXT("RastDrawPrimitives2", pDPrim2Data);', `
VALIDATE_REFRAST_CONTEXT("RefRastDrawPrimitives", pDPrim2Data);')
if (pDPrim2Data->dwFlags & D3DHALDP2_USERMEMVERTICES)
pVtData = (PUINT8)pDPrim2Data->lpVertices + 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;
ifelse(`$1', `Rast', `
// Check for FVF vertex, and init FVF related fileds if necessary
CHECK_FVF(pDPrim2Data->ddrval, pDCtx, (DWORD)pDPrim2Data->dwVertexType);', `
// Unconditionally get the vertex stride, since it can not change
if ((pDPrim2Data->ddrval = FVFCheckAndStride(
(DWORD)pDPrim2Data->dwVertexType, &dwStride)) != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}
if ((pDPrim2Data->ddrval=RefRastLockTarget(pRefRast)) != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}')dnl
// 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.
//
if (pCmd->bCommand != D3DDP2OP_RENDERSTATE &&
pCmd->bCommand != D3DDP2OP_TEXTURESTAGESTATE)
{
ifelse(`$1', `Rast', `
pDPrim2Data->ddrval = pDCtx->Begin();
if (pDPrim2Data->ddrval != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}', `
if ((pDPrim2Data->ddrval=RefRastLockTexture(pRefRast)) != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}
if ((pDPrim2Data->ddrval =
pRefRast->BeginRendering((DWORD)pDPrim2Data->dwVertexType)) != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}')
}
// 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;
ifelse(`$1', `Rast', `
D3DPRIMITIVETYPE Primtype =
ConvertDP2OPToPrimType((D3DHAL_DP2OPERATION)pCmd->bCommand);
if (Primtype > 0)
{
pDCtx->BeginPrimSet(Primtype, pDCtx->GetFvfVertexType());
}
BOOL bWireframe =
(pDCtx->GetRastCtx())->pdwRenderState[D3DRENDERSTATE_FILLMODE]
== D3DFILL_WIREFRAME;
pDPrim2Data->ddrval = DoDrawPrimitives2((LPVOID)pDCtx,
pDCtx->GetFunsTbl(),
(UINT16)pDCtx->GetFvfStride(),
(DWORD)pDPrim2Data->dwVertexType,
pVtData,
&pCmd,
lpdwRStates,
bWireframe
);', `
BOOL bWireframe = pRefRast->GetRenderState()[D3DRENDERSTATE_FILLMODE]
== D3DFILL_WIREFRAME;
pDPrim2Data->ddrval = DoDrawPrimitives2((LPVOID)pRefRast,
(PRIMITIVE_FUNTIONS *)
(((PUINT8)pRefRast->GetUserPrivate())+sizeof(D3DFE_STATESET)),
(UINT16)dwStride,
(DWORD)pDPrim2Data->dwVertexType,
pVtData,
&pCmd,
lpdwRStates,
bWireframe
);')
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:
ifelse(`$1', `Rast', `
hr = pDCtx->End();', `
hr = pRefRast->EndRendering();
RefRastUnlockTexture(pRefRast);
RefRastUnlockTarget(pRefRast);')
if (pDPrim2Data->ddrval == D3D_OK)
{
pDPrim2Data->ddrval = hr;
}
return DDHAL_DRIVER_HANDLED;
}')
d_DrawPrim2(`Rast')
dnl
dnl Now the d3dref.dll is used for all RefRast rendering
dnl
dnl d_DrawPrim2(`RefRast')
HRESULT FASTCALL
DoDrawIndexedTriList2(LPVOID pCtx,
PRIMITIVE_FUNTIONS *pfnPrims,
DWORD dwStride,
PUINT8 pVtx,
WORD cPrims,
D3DHAL_DP2INDEXEDTRIANGLELIST *pTriList)
{
INT i;
D3DHAL_DP2INDEXEDTRIANGLELIST *pTri = pTriList;
for (i = 0; i < cPrims; i ++)
{
HRESULT hr;
PUINT8 pVtx0, pVtx1, pVtx2;
pVtx0 = pVtx + dwStride * pTri->wV1;
pVtx1 = pVtx + dwStride * pTri->wV2;
pVtx2 = pVtx + dwStride * pTri->wV3;
HR_RET(pfnPrims->pfnTri(pCtx,
pVtx0,
pVtx1,
pVtx2,
pTri->wFlags));
pTri ++;
}
return D3D_OK;
}
//----------------------------------------------------------------------------
//
// DoDrawPrimitives2
//
// It's called by RastDrawPrimitives2. .
//
//----------------------------------------------------------------------------
HRESULT FASTCALL
DoDrawPrimitives2(LPVOID pCtx,
PRIMITIVE_FUNTIONS *pfnPrims,
UINT16 dwStride,
DWORD dwFvf,
PUINT8 pVtx,
LPD3DHAL_DP2COMMAND *ppCmd,
LPDWORD lpdwRStates,
BOOL bWireframe
)
{
LPD3DHAL_DP2COMMAND pCmd = *ppCmd;
HRESULT hr;
D3D_INFO(7, "(Rast)Read Ins: %08lx", *(LPDWORD)pCmd);
switch(pCmd->bCommand)
{
case D3DDP2OP_VIEWPORTINFO:
{
HR_RET(pfnPrims->pfnDp2SetViewport(pCtx, pCmd));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)
((D3DHAL_DP2VIEWPORTINFO *)(pCmd + 1) + pCmd->wStateCount);
}
break;
case D3DDP2OP_WINFO:
{
HR_RET(pfnPrims->pfnDp2SetWRange(pCtx, pCmd));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)
((D3DHAL_DP2WINFO *)(pCmd + 1) + pCmd->wStateCount);
}
break;
case D3DDP2OP_RENDERSTATE:
{
HR_RET(pfnPrims->pfnDp2SetRenderStates(pCtx, dwFvf, pCmd, lpdwRStates));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)
((D3DHAL_DP2RENDERSTATE *)(pCmd + 1) + pCmd->wStateCount);
}
break;
case D3DDP2OP_TEXTURESTAGESTATE:
{
HR_RET(pfnPrims->pfnDp2TextureStageState(pCtx, 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 DoDrawOneIndexedPrimitive/DoDrawOnePrimitive.
case D3DDP2OP_INDEXEDTRIANGLELIST:
{
WORD cPrims = pCmd->wPrimitiveCount;
HR_RET(DoDrawIndexedTriList2(pCtx,
pfnPrims,
dwStride,
pVtx,
cPrims,
(D3DHAL_DP2INDEXEDTRIANGLELIST *)(pCmd + 1)));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST) * cPrims);
}
break;
case D3DDP2OP_INDEXEDLINELIST:
{
HR_RET(DoDrawOneIndexedPrimitive(pCtx,
pfnPrims,
dwStride,
pVtx,
(LPWORD)(pCmd + 1),
D3DPT_LINELIST,
pCmd->wPrimitiveCount * 2));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
}
break;
// Following ops All use DoDrawOneIndexedPrimitive/DoDrawOnePrimitive.
// 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 DoDrawOneIndexedPrimitive/DoDrawOnePrimitive
// here anyway. We can later change it if necessary.
case D3DDP2OP_POINTS:
{
WORD cPrims = pCmd->wPrimitiveCount;
WORD i;
D3DHAL_DP2POINTS *pPt = (D3DHAL_DP2POINTS *)(pCmd + 1);
for (i = 0; i < cPrims; i++)
{
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
(pVtx + pPt->wVStart * dwStride),
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);
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
(pVtx + pLine->wVStart * dwStride),
D3DPT_LINELIST,
pCmd->wPrimitiveCount * 2));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
}
break;
case D3DDP2OP_INDEXEDLINELIST2:
{
LPD3DHAL_DP2STARTVERTEX lpStartVertex;
lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
HR_RET(DoDrawOneIndexedPrimitive(pCtx,
pfnPrims,
dwStride,
pVtx + lpStartVertex->wVStart*dwStride,
(LPWORD)(lpStartVertex + 1),
D3DPT_LINELIST,
pCmd->wPrimitiveCount * 2));
// 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);
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
(pVtx + pLine->wVStart * dwStride),
D3DPT_LINESTRIP,
pCmd->wPrimitiveCount + 1));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
}
break;
case D3DDP2OP_INDEXEDLINESTRIP:
{
DWORD vertexCount = pCmd->wPrimitiveCount + 1;
LPD3DHAL_DP2STARTVERTEX lpStartVertex;
lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
HR_RET(DoDrawOneIndexedPrimitive(pCtx,
pfnPrims,
dwStride,
pVtx + lpStartVertex->wVStart*dwStride,
(LPWORD)(lpStartVertex + 1),
D3DPT_LINESTRIP,
vertexCount));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
vertexCount * sizeof(WORD));
}
break;
case D3DDP2OP_TRIANGLELIST:
{
D3DHAL_DP2TRIANGLELIST *pTri = (D3DHAL_DP2TRIANGLELIST *)(pCmd + 1);
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
(pVtx + pTri->wVStart * dwStride),
D3DPT_TRIANGLELIST,
pCmd->wPrimitiveCount * 3));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
}
break;
case D3DDP2OP_INDEXEDTRIANGLELIST2:
{
DWORD vertexCount = pCmd->wPrimitiveCount*3;
LPD3DHAL_DP2STARTVERTEX lpStartVertex;
lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
HR_RET(DoDrawOneIndexedPrimitive(pCtx,
pfnPrims,
dwStride,
pVtx + lpStartVertex->wVStart*dwStride,
(LPWORD)(lpStartVertex + 1),
D3DPT_TRIANGLELIST,
vertexCount));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
vertexCount * sizeof(WORD));
}
break;
case D3DDP2OP_TRIANGLESTRIP:
{
D3DHAL_DP2TRIANGLESTRIP *pTri = (D3DHAL_DP2TRIANGLESTRIP *)(pCmd + 1);
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
(pVtx + pTri->wVStart * dwStride),
D3DPT_TRIANGLESTRIP,
pCmd->wPrimitiveCount + 2));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
}
break;
case D3DDP2OP_INDEXEDTRIANGLESTRIP:
{
DWORD vertexCount = pCmd->wPrimitiveCount+2;
LPD3DHAL_DP2STARTVERTEX lpStartVertex;
lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
HR_RET(DoDrawOneIndexedPrimitive(pCtx,
pfnPrims,
dwStride,
pVtx + lpStartVertex->wVStart*dwStride,
(LPWORD)(lpStartVertex + 1),
D3DPT_TRIANGLESTRIP,
vertexCount));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
vertexCount * sizeof(WORD));
}
break;
case D3DDP2OP_TRIANGLEFAN:
{
D3DHAL_DP2TRIANGLEFAN *pTri = (D3DHAL_DP2TRIANGLEFAN *)(pCmd + 1);
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
(pVtx + pTri->wVStart * dwStride),
D3DPT_TRIANGLEFAN,
pCmd->wPrimitiveCount + 2));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
}
break;
case D3DDP2OP_INDEXEDTRIANGLEFAN:
{
DWORD vertexCount = pCmd->wPrimitiveCount + 2;
LPD3DHAL_DP2STARTVERTEX lpStartVertex;
lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
HR_RET(DoDrawOneIndexedPrimitive(pCtx,
pfnPrims,
dwStride,
pVtx + lpStartVertex->wVStart*dwStride,
(LPWORD)(lpStartVertex + 1),
D3DPT_TRIANGLEFAN,
vertexCount));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
vertexCount * 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);
if (bWireframe)
{
// Read edge flags
UINT32 dwEdgeFlags =
((LPD3DHAL_DP2TRIANGLEFAN_IMM)(pCmd + 1))->dwEdgeFlags;
HR_RET(DoDrawOneEdgeFlagTriangleFan(pCtx,
pfnPrims,
dwStride,
pFanVtx,
vertexCount,
dwEdgeFlags));
}
else
{
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
pFanVtx,
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);
HR_RET(DoDrawOnePrimitive(pCtx,
pfnPrims,
dwStride,
pLineVtx,
D3DPT_LINELIST,
vertexCount));
// Update the command buffer pointer
*ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pLineVtx +
vertexCount * dwStride);
}
break;
default :
hr = D3DParseUnknownCommand((LPVOID)pCmd, (LPVOID*)ppCmd);
break;
}
return hr;
}