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