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