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.
 
 
 
 
 
 

827 lines
25 KiB

//----------------------------------------------------------------------------
//
// drawprim.cpp
//
// Implements DrawOnePrimitive, DrawOneIndexedPrimitive and
// DrawPrimitives.
//
// Copyright (C) Microsoft Corporation, 1997.
//
//----------------------------------------------------------------------------
#include "pch.cpp"
#pragma hdrstop
//----------------------------------------------------------------------------
//
// CheckFVF
//
// Check a FVF control word and then init m_fvfData accordingly
//
//----------------------------------------------------------------------------
HRESULT FASTCALL
D3DContext::CheckFVF(DWORD dwFVF)
{
// check if FVF controls have changed
if ( (m_fvfData.preFVF == dwFVF) &&
(m_fvfData.TexIdx[0] == (INT)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_TEXCOORDINDEX)]) &&
(m_fvfData.TexIdx[1] == (INT)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_TEXCOORDINDEX)]) &&
(m_fvfData.cActTex == m_RastCtx.cActTex) )
{
return D3D_OK;
}
#if DBG
// This is added here per Iouri's request. It will make it easier for him
// to test his code for legacy drivers.
if (dwFVF == 0)
{
dwFVF = D3DFVF_TLVERTEX;
}
#endif
memset(&m_fvfData, 0, sizeof(FVFDATA));
m_fvfData.preFVF = dwFVF;
m_fvfData.TexIdx[0] = m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_TEXCOORDINDEX)];
m_fvfData.TexIdx[1] = m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_TEXCOORDINDEX)];
m_fvfData.cActTex = m_RastCtx.cActTex;
#if DBG
// We only support max 8 texture coords
if (m_fvfData.TexIdx[0] > 7 || m_fvfData.TexIdx[1] > 7)
{
D3D_WARN(0, "(Rast) Texture coord index bigger than max supported.");
return DDERR_INVALIDPARAMS;
}
#endif
// Update the copy of wrap states in RastCtx
m_RastCtx.pdwWrap[0] = m_RastCtx.pdwRenderState[
(D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0+m_fvfData.TexIdx[0])];
m_RastCtx.pdwWrap[1] = m_RastCtx.pdwRenderState[
(D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0+m_fvfData.TexIdx[1])];
// do either true FVF parsing or legacy TLVERTEX handling
if ( (m_RastCtx.BeadSet != D3DIBS_RAMP) &&
( (dwFVF != D3DFVF_TLVERTEX) ||
(0 != m_fvfData.TexIdx[0]) ||
(m_RastCtx.cActTex > 1) ) )
{ // New (non TL)FVF vertex
// XYZ
if ( (dwFVF & (D3DFVF_RESERVED0 | D3DFVF_RESERVED1 | D3DFVF_RESERVED2 |
D3DFVF_NORMAL)) ||
((dwFVF & (D3DFVF_XYZ | D3DFVF_XYZRHW)) == 0) )
{
// can't set reserved bits, shouldn't have normals in
// output to rasterizers, and must have coordinates
return DDERR_INVALIDPARAMS;
}
m_fvfData.stride = sizeof(D3DVALUE) * 3;
if (dwFVF & D3DFVF_XYZRHW)
{
m_fvfData.offsetRHW = m_fvfData.stride;
m_fvfData.stride += sizeof(D3DVALUE);
}
if (dwFVF & D3DFVF_DIFFUSE)
{
m_fvfData.offsetDiff = m_fvfData.stride;
m_fvfData.stride += sizeof(D3DCOLOR);
}
if (dwFVF & D3DFVF_SPECULAR)
{
m_fvfData.offsetSpec = m_fvfData.stride;
m_fvfData.stride += sizeof(D3DCOLOR);
}
INT iTexCount = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
#if DBG
INT iTexIdx0 = m_fvfData.TexIdx[0], iTexIdx1 = m_fvfData.TexIdx[1];
if (iTexCount > 0)
{
if ( iTexIdx0 >= iTexCount)
{
D3D_WARN(1, "(Rast)Texture coord index bigger than texture coord count.");
iTexIdx0 = 0;
}
if ( iTexIdx1 >= iTexCount)
{
D3D_WARN(1, "(Rast)Texture coord index bigger than texture coord count.");
iTexIdx1 = 0;
}
// set offset for Textures 0 and 1
m_fvfData.offsetTex0 = (INT16)(m_fvfData.stride +
2*sizeof(D3DVALUE)*iTexIdx0);
m_fvfData.offsetTex1 = (INT16)(m_fvfData.stride +
2*sizeof(D3DVALUE)*iTexIdx1);
// update stride
m_fvfData.stride += (INT16)(iTexCount * (sizeof(D3DVALUE) * 2));
}
#else
if (iTexCount > 0)
{
// set offset for Textures 0 and 1
m_fvfData.offsetTex0 = (INT16)(m_fvfData.stride +
2*sizeof(D3DVALUE)*m_fvfData.TexIdx[0]);
m_fvfData.offsetTex1 = (INT16)(m_fvfData.stride +
2*sizeof(D3DVALUE)*m_fvfData.TexIdx[1]);
// update stride
m_fvfData.stride += (INT16)(iTexCount * (sizeof(D3DVALUE) * 2));
}
#endif
m_fvfData.vtxType = RAST_GENVERTEX;
}
else
{
// (Legacy) TL vertex
if (0 < m_fvfData.TexIdx[0])
{
D3D_ERR("(Rast) Texture coord index bigger than 0 for legacy TL vertex.");
return DDERR_INVALIDPARAMS;
}
m_fvfData.stride = sizeof(D3DTLVERTEX);
m_fvfData.vtxType = RAST_TLVERTEX;
}
UpdatePrimFunctionTbl();
return D3D_OK;
}
//----------------------------------------------------------------------------
//
// PackGenVertex
//
// Pack a FvFVertex into RAST_GENERIC_VERTEX. This is called for every non TL
// FVF vertex. It can be optimized for speed later.
//
//----------------------------------------------------------------------------
void FASTCALL
D3DContext::PackGenVertex(PUINT8 pFvfVtx, RAST_GENERIC_VERTEX *pGenVtx)
{
pGenVtx->sx = *((D3DVALUE *)pFvfVtx);
pGenVtx->sy = *((D3DVALUE *)pFvfVtx + 1);
pGenVtx->sz = *((D3DVALUE *)pFvfVtx + 2);
if (m_fvfData.offsetRHW)
{
pGenVtx->rhw = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetRHW));
}
else
{
pGenVtx->rhw = 1.0f;
}
if (m_fvfData.offsetDiff)
{
pGenVtx->color = *((D3DCOLOR *)(pFvfVtx + m_fvfData.offsetDiff));
}
else
{
pGenVtx->color = __DEFAULT_DIFFUSE;
}
if (m_fvfData.offsetSpec)
{
pGenVtx->specular = *((D3DCOLOR *)(pFvfVtx + m_fvfData.offsetSpec));
}
else
{
pGenVtx->specular = __DEFAULT_SPECULAR;
}
if (m_fvfData.offsetTex0)
{
pGenVtx->tu = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex0));
pGenVtx->tv = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex0) + 1);
}
else
{
pGenVtx->tu = 0.0f;
pGenVtx->tv = 0.0f;
}
if (m_fvfData.offsetTex1)
{
pGenVtx->tu2 = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex1));
pGenVtx->tv2 = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex1) + 1);
}
else
{
pGenVtx->tu2 = 0.0f;
pGenVtx->tv2 = 0.0f;
}
}
//----------------------------------------------------------------------------
//
// DoDrawOnePrimitive
//
// Draw one list of primitives. It's called by both RastDrawOnePrimitive and
// RastDrawPrimitives.
//
//----------------------------------------------------------------------------
HRESULT FASTCALL
DoDrawOnePrimitive(LPVOID pCtx,
PRIMITIVE_FUNTIONS *pfnPrims,
UINT16 FvfStride,
PUINT8 pVtx,
D3DPRIMITIVETYPE PrimType,
UINT cVertices)
{
INT i;
PUINT8 pV0, pV1, pV2;
HRESULT hr;
switch (PrimType)
{
case D3DPT_POINTLIST:
for (i = (INT)cVertices; i > 0; i--)
{
HR_RET(pfnPrims->pfnPoint(pCtx, pVtx));
pVtx += FvfStride;
}
break;
case D3DPT_LINELIST:
for (i = (INT)cVertices / 2; i > 0; i--)
{
pV0 = pVtx;
pVtx += FvfStride;
pV1 = pVtx;
pVtx += FvfStride;
HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
}
break;
case D3DPT_LINESTRIP:
{
pV1 = pVtx;
// Disable last-pixel setting for shared verties and store prestate.
pfnPrims->pfnStoreLastPixelState(pCtx, 1);
// Initial pV0.
for (i = (INT)cVertices - 1; i > 1; i--)
{
pV0 = pV1;
pVtx += FvfStride;
pV1 = pVtx;
HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
}
// Restore last-pixel setting.
pfnPrims->pfnStoreLastPixelState(pCtx, 0);
// Draw last line with last-pixel setting from state.
if (i == 1)
{
pV0 = pVtx + FvfStride;
HR_RET(pfnPrims->pfnLine(pCtx, pV1, pV0));
}
}
break;
case D3DPT_TRIANGLELIST:
for (i = (INT)cVertices; i > 0; i -= 3)
{
pV0 = pVtx;
pVtx += FvfStride;
pV1 = pVtx;
pVtx += FvfStride;
pV2 = pVtx;
pVtx += FvfStride;
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
}
break;
case D3DPT_TRIANGLESTRIP:
{
// Get initial vertex values.
pV1 = pVtx;
pVtx += FvfStride;
pV2 = pVtx;
pVtx += FvfStride;
for (i = (INT)cVertices - 2; i > 1; i -= 2)
{
pV0 = pV1;
pV1 = pV2;
pV2 = pVtx;
pVtx += FvfStride;
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
pV0 = pV1;
pV1 = pV2;
pV2 = pVtx;
pVtx += FvfStride;
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV2, pV1, PFN_TRIANGLE_5ARG_DEFAULT));
}
if (i > 0)
{
pV0 = pV1;
pV1 = pV2;
pV2 = pVtx;
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
}
}
break;
case D3DPT_TRIANGLEFAN:
{
pV2 = pVtx;
pVtx += FvfStride;
// Preload initial pV0.
pV1 = pVtx;
pVtx += FvfStride;
for (i = (INT)cVertices - 2; i > 0; i--)
{
pV0 = pV1;
pV1 = pVtx;
pVtx += FvfStride;
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
}
}
break;
default:
D3D_ERR("(Rast) Unknown or unsupported primitive type "
"requested of DrawOnePrimitive");
return DDERR_INVALIDPARAMS;
}
return D3D_OK;
}
//----------------------------------------------------------------------------
//
// DoDrawOneIndexedPrimitive
//
// Draw one list of indexed primitives. It's called by
// RastDrawOneIndexedPrimitive.
//
//----------------------------------------------------------------------------
HRESULT FASTCALL
DoDrawOneIndexedPrimitive(LPVOID pCtx,
PRIMITIVE_FUNTIONS *pfnPrims,
UINT16 FvfStride,
PUINT8 pVtx,
LPWORD puIndices,
D3DPRIMITIVETYPE PrimType,
UINT cIndices)
{
INT i;
PUINT8 pV0, pV1, pV2;
HRESULT hr;
switch(PrimType)
{
case D3DPT_POINTLIST:
for (i = (INT)cIndices; i > 0; i--)
{
pV0 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnPoint(pCtx, pV0));
}
break;
case D3DPT_LINELIST:
for (i = (INT)cIndices / 2; i > 0; i--)
{
pV0 = pVtx + FvfStride * (*puIndices++);
pV1 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
}
break;
case D3DPT_LINESTRIP:
{
// Disable last-pixel setting for shared verties and store prestate.
pfnPrims->pfnStoreLastPixelState(pCtx, 1);
// Initial pV1.
pV1 = pVtx + FvfStride * (*puIndices++);
for (i = (INT)cIndices - 1; i > 1; i--)
{
pV0 = pV1;
pV1 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
}
// Restore last-pixel setting.
pfnPrims->pfnStoreLastPixelState(pCtx, 0);
// Draw last line with last-pixel setting from state.
if (i == 1)
{
pV0 = pVtx + FvfStride * (*puIndices);
HR_RET(pfnPrims->pfnLine(pCtx, pV1, pV0));
}
}
break;
case D3DPT_TRIANGLELIST:
for (i = (INT)cIndices; i > 0; i -= 3)
{
pV0 = pVtx + FvfStride * (*puIndices++);
pV1 = pVtx + FvfStride * (*puIndices++);
pV2 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
}
break;
case D3DPT_TRIANGLESTRIP:
{
// Get initial vertex values.
pV1 = pVtx + FvfStride * (*puIndices++);
pV2 = pVtx + FvfStride * (*puIndices++);
for (i = (INT)cIndices - 2; i > 1; i -= 2)
{
pV0 = pV1;
pV1 = pV2;
pV2 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
pV0 = pV1;
pV1 = pV2;
pV2 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV2, pV1, PFN_TRIANGLE_5ARG_DEFAULT));
}
if (i > 0)
{
pV0 = pV1;
pV1 = pV2;
pV2 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
}
}
break;
case D3DPT_TRIANGLEFAN:
{
pV2 = pVtx + FvfStride * (*puIndices++);
// Preload initial pV0.
pV1 = pVtx + FvfStride * (*puIndices++);
for (i = (INT)cIndices - 2; i > 0; i--)
{
pV0 = pV1;
pV1 = pVtx + FvfStride * (*puIndices++);
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
}
}
break;
default:
D3D_ERR("(Rast) Unknown or unsupported primitive type "
"requested of DrawOneIndexedPrimitive");
return DDERR_INVALIDPARAMS;
}
return D3D_OK;
}
//----------------------------------------------------------------------------
//
// DoDrawOneEdgeFlagTriangleFan
//
// Draw one list of triangle fans. It's called by both RastDrawOnePrimitive and
// RastDrawPrimitives.
//
//----------------------------------------------------------------------------
HRESULT FASTCALL
DoDrawOneEdgeFlagTriangleFan(LPVOID pCtx,
PRIMITIVE_FUNTIONS *pfnPrims,
UINT16 FvfStride,
PUINT8 pVtx,
UINT cVertices,
UINT32 dwEdgeFlags)
{
INT i;
PUINT8 pV0, pV1, pV2;
HRESULT hr;
pV2 = pVtx;
pVtx += FvfStride;
pV0 = pVtx;
pVtx += FvfStride;
pV1 = pVtx;
pVtx += FvfStride;
WORD wFlags = 0;
if(dwEdgeFlags & 0x2)
wFlags |= D3DTRIFLAG_EDGEENABLE1;
if(dwEdgeFlags & 0x1)
wFlags |= D3DTRIFLAG_EDGEENABLE3;
if(cVertices == 3) {
if(dwEdgeFlags & 0x4)
wFlags |= D3DTRIFLAG_EDGEENABLE2;
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, wFlags));
return D3D_OK;
}
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, wFlags));
UINT32 dwMask = 0x4;
for (i = (INT)cVertices - 4; i > 0; i--)
{
pV0 = pV1;
pV1 = pVtx;
pVtx += FvfStride;
if(dwEdgeFlags & dwMask)
{
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, D3DTRIFLAG_EDGEENABLE1));
}
else
{
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, 0));
}
dwMask <<= 1;
}
pV0 = pV1;
pV1 = pVtx;
wFlags = 0;
if(dwEdgeFlags & dwMask)
wFlags |= D3DTRIFLAG_EDGEENABLE1;
dwMask <<= 1;
if(dwEdgeFlags & dwMask)
wFlags |= D3DTRIFLAG_EDGEENABLE2;
HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, wFlags));
return D3D_OK;
}
#if DBG
//----------------------------------------------------------------------------
//
// ValidatePrimType
//
// Check if the primitive type is supported. We could remove this function
// after we have implemented all primitive types and then depend on D3DIM
// to check if the primitive type is valid.
//
//----------------------------------------------------------------------------
inline HRESULT
D3DContext::ValidatePrimType(D3DPRIMITIVETYPE PrimitiveType)
{
switch(PrimitiveType)
{
case D3DPT_POINTLIST:
case D3DPT_LINELIST:
case D3DPT_LINESTRIP:
case D3DPT_TRIANGLELIST:
case D3DPT_TRIANGLEFAN:
case D3DPT_TRIANGLESTRIP:
break;
default:
D3D_ERR("(Rast) PrimitiveType not supported by the new rasterizer.");
return DDERR_INVALIDPARAMS;
}
return D3D_OK;
}
#endif
//----------------------------------------------------------------------------
//
// CheckDrawOnePrimitive
//
// Check if the DRAWONEPRIMITIVEDATA is valid.
//
//----------------------------------------------------------------------------
inline HRESULT
D3DContext::CheckDrawOnePrimitive(LPD3DHAL_DRAWONEPRIMITIVEDATA pOnePrimData)
{
#if DBG
HRESULT hr;
if (pOnePrimData == NULL ||
pOnePrimData->dwhContext == 0 ||
pOnePrimData->lpvVertices == NULL)
{
D3D_ERR("(Rast) Invalid data passed to the new rasterizer.");
return DDERR_INVALIDPARAMS;
}
HR_RET(ValidatePrimType(pOnePrimData->PrimitiveType));
#endif
return D3D_OK;
}
//----------------------------------------------------------------------------
//
// CheckDrawOneIndexedPrimitive
//
// Check if the DRAWONEINDEXEDPRIMITIVEDATA is valid.
//
//----------------------------------------------------------------------------
inline HRESULT
D3DContext::CheckDrawOneIndexedPrimitive(
LPD3DHAL_DRAWONEINDEXEDPRIMITIVEDATA pOneIdxPrimData)
{
#if DBG
HRESULT hr;
if (pOneIdxPrimData == NULL ||
pOneIdxPrimData->dwhContext == 0 ||
pOneIdxPrimData->lpvVertices == NULL ||
pOneIdxPrimData->lpwIndices == NULL)
{
D3D_ERR("(Rast) Invalid data passed to the new rasterizer.");
return DDERR_INVALIDPARAMS;
}
HR_RET(ValidatePrimType(pOneIdxPrimData->PrimitiveType));
#endif
return D3D_OK;
}
//----------------------------------------------------------------------------
//
// RastDrawOnePrimitive
//
// Draw one list of primitives. This is called by D3DIM for API DrawPrimitive.
//
//----------------------------------------------------------------------------
DWORD __stdcall
RastDrawOnePrimitive(LPD3DHAL_DRAWONEPRIMITIVEDATA pOnePrimData)
{
HRESULT hr;
D3DContext *pDCtx;
VALIDATE_D3DCONTEXT("RastDrawOnePrimitive", pOnePrimData);
if ((pOnePrimData->ddrval =
pDCtx->CheckDrawOnePrimitive(pOnePrimData)) != DD_OK)
{
return DDHAL_DRIVER_HANDLED;
}
// Check for FVF vertex, and init FVF related fileds if necessary
// Assume the control word is passed in through dwFlags
CHECK_FVF(pOnePrimData->ddrval, pDCtx, (DWORD)pOnePrimData->dwFVFControl);
pOnePrimData->ddrval = pDCtx->Begin();
if (pOnePrimData->ddrval != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}
pOnePrimData->ddrval =
pDCtx->DrawOnePrimitive((PUINT8)pOnePrimData->lpvVertices,
pOnePrimData->PrimitiveType,
pOnePrimData->dwNumVertices);
hr = pDCtx->End();
if (pOnePrimData->ddrval == D3D_OK)
{
pOnePrimData->ddrval = hr;
}
return DDHAL_DRIVER_HANDLED;
}
//----------------------------------------------------------------------------
//
// RastDrawOneIndexedPrimitive
//
// Draw one list of primitives. This is called by D3DIM for API
// DrawIndexedPrimitive.
//
//----------------------------------------------------------------------------
DWORD __stdcall
RastDrawOneIndexedPrimitive(LPD3DHAL_DRAWONEINDEXEDPRIMITIVEDATA
pOneIdxPrimData)
{
HRESULT hr;
D3DContext *pDCtx;
VALIDATE_D3DCONTEXT("RastDrawOneIndexedPrimitive", pOneIdxPrimData);
if ((pOneIdxPrimData->ddrval =
pDCtx->CheckDrawOneIndexedPrimitive(pOneIdxPrimData)) != DD_OK)
{
return DDHAL_DRIVER_HANDLED;
}
// Check for FVF vertex, and init FVF related fileds if necessary
// Assume the control word is passed in through dwFlags
CHECK_FVF(pOneIdxPrimData->ddrval, pDCtx, (DWORD)pOneIdxPrimData->dwFVFControl);
pOneIdxPrimData->ddrval = pDCtx->Begin();
if (pOneIdxPrimData->ddrval != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}
pOneIdxPrimData->ddrval =
pDCtx->DrawOneIndexedPrimitive((PUINT8)pOneIdxPrimData->lpvVertices,
pOneIdxPrimData->lpwIndices,
pOneIdxPrimData->PrimitiveType,
pOneIdxPrimData->dwNumIndices);
hr = pDCtx->End();
if (pOneIdxPrimData->ddrval == D3D_OK)
{
pOneIdxPrimData->ddrval = hr;
}
return DDHAL_DRIVER_HANDLED;
}
//----------------------------------------------------------------------------
//
// RastDrawPrimitives
//
// This is called by D3DIM for a list of batched API DrawPrimitive calls.
//
//----------------------------------------------------------------------------
DWORD __stdcall
RastDrawPrimitives(LPD3DHAL_DRAWPRIMITIVESDATA pDrawPrimData)
{
PUINT8 pData = (PUINT8)pDrawPrimData->lpvData;
LPD3DHAL_DRAWPRIMCOUNTS pDrawPrimitiveCounts;
D3DContext *pDCtx;
VALIDATE_D3DCONTEXT("RastDrawPrimitives", pDrawPrimData);
pDrawPrimitiveCounts = (LPD3DHAL_DRAWPRIMCOUNTS)pData;
// Check for FVF vertex when there are actually something to be drawn, and
// init FVF related fileds if necessary Assume the control word is passed
// in through dwReserved
if (pDrawPrimitiveCounts->wNumVertices > 0)
{
CHECK_FVF(pDrawPrimData->ddrval, pDCtx, pDrawPrimData->dwFVFControl);
}
// Skip state check and texture lock if the first thing is state change
if (pDrawPrimitiveCounts->wNumStateChanges == 0)
{
pDrawPrimData->ddrval =pDCtx->Begin();
if (pDrawPrimData->ddrval != D3D_OK)
{
goto EH_Exit;
}
}
// Loop through the data, update render states
// and then draw the primitive
for (;;)
{
pDrawPrimitiveCounts = (LPD3DHAL_DRAWPRIMCOUNTS)pData;
pData += sizeof(D3DHAL_DRAWPRIMCOUNTS);
//
// Update render states
//
if (pDrawPrimitiveCounts->wNumStateChanges > 0)
{
// Flush the prim proc before any state changs
pDrawPrimData->ddrval = pDCtx->End(FALSE);
if (pDrawPrimData->ddrval != D3D_OK)
{
return DDHAL_DRIVER_HANDLED;
}
pDrawPrimData->ddrval =
pDCtx->UpdateRenderStates((LPDWORD)pData,
pDrawPrimitiveCounts->wNumStateChanges);
if (pDrawPrimData->ddrval != D3D_OK)
{
goto EH_Exit;
}
pData += pDrawPrimitiveCounts->wNumStateChanges *
sizeof(DWORD) * 2;
}
// Check for exit
if (pDrawPrimitiveCounts->wNumVertices == 0)
{
break;
}
// Align pointer to vertex data
pData = (PUINT8)
((UINT_PTR)(pData + (DP_VTX_ALIGN - 1)) & ~(DP_VTX_ALIGN - 1));
// Delayed change until we really need to render something
if (pDrawPrimitiveCounts->wNumStateChanges > 0)
{
// We might have a new texture so lock.
pDrawPrimData->ddrval = pDCtx->Begin();
if (pDrawPrimData->ddrval != D3D_OK)
{
goto EH_Exit;
}
}
//
// Primitives
//
pDrawPrimData->ddrval =
pDCtx->DrawOnePrimitive((PUINT8)pData,
(D3DPRIMITIVETYPE)pDrawPrimitiveCounts->wPrimitiveType,
pDrawPrimitiveCounts->wNumVertices);
if (pDrawPrimData->ddrval != DD_OK)
{
goto EH_Exit;
}
pData += pDrawPrimitiveCounts->wNumVertices * pDCtx->GetFvfStride();
}
EH_Exit:
HRESULT hr;
hr = pDCtx->End();
if (pDrawPrimData->ddrval == D3D_OK)
{
pDrawPrimData->ddrval = hr;
}
return DDHAL_DRIVER_HANDLED;
}