/*==========================================================================; * * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved. * * File: drawprim.hpp * Content: DrawPrimitive common defines * ***************************************************************************/ #ifndef _DRAWPRIM_H_ #define _DRAWPRIM_H_ #define MAX_DX6_VERTICES ((1<<16) - 1) #ifdef WIN95 #define LOWVERTICESNUMBER 128 #else #define LOWVERTICESNUMBER 96 #endif #define D3D_MAX_TLVBUF_CHANGES 5 // All vertices from lpDevI->lpVout are copied to the output buffer, expanding // to D3DTLVERTEX. // The output buffer is lpAddress if it is not NULL, otherwise it is TLVbuf // //--------------------------------------------------------------------- #define FVF_TRANSFORMED(dwFVF) ((dwFVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) #define FVF_TEXCOORD_NUMBER(dwFVF) \ (((dwFVF) & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) //--------------------------------------------------------------------- // Computes size in bytes of the position component of a vertex // __inline DWORD GetPositionSizeFVF(DWORD fvf) { DWORD size = 3 << 2; switch (fvf & D3DFVF_POSITION_MASK) { case D3DFVF_XYZRHW: size += 4; break; case D3DFVF_XYZB1: size += 1*4; break; case D3DFVF_XYZB2: size += 2*4; break; case D3DFVF_XYZB3: size += 3*4; break; case D3DFVF_XYZB4: size += 4*4; break; case D3DFVF_XYZB5: size += 5*4; break; } return size; } //--------------------------------------------------------------------- // Computes vertex size in bytes for a the vertex ID excluding size of // texture oordinates // __inline DWORD GetVertexSizeFVF(DWORD fvf) { DWORD size = GetPositionSizeFVF(fvf); if (fvf & D3DFVF_NORMAL) size += 3*4; if (fvf & D3DFVF_PSIZE) size += 4; if (fvf & D3DFVF_DIFFUSE) size+= 4; if (fvf & D3DFVF_SPECULAR) size += 4; if (fvf & D3DFVF_FOG) size += 4; return size; } //--------------------------------------------------------------------- // 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 }; //--------------------------------------------------------------------- // Computes vertex size in bytes from the vertex ID // // Texture formats size 00 01 10 11 const BYTE g_TextureSize[4] = {2*4, 3*4, 4*4, 4}; //--------------------------------------------------------------------- // Index is number of floats in a texture coordinate set. // Value is texture format bits // const DWORD g_dwTextureFormat[5] = {0, 3, 0, 1, 2}; //--------------------------------------------------------------------- // Returns total size of texture coordinates // Computes dwTextureCoordSize[] array - size of every texture coordinate set // inline DWORD ComputeTextureCoordSize(DWORD dwFVF, DWORD *dwTextureCoordSize) { DWORD dwNumTexCoord = FVF_TEXCOORD_NUMBER(dwFVF); DWORD dwTextureCoordSizeTotal; // Compute texture coordinate size DWORD dwTextureFormats = dwFVF >> 16; if (dwTextureFormats == 0) { dwTextureCoordSizeTotal = (BYTE)dwNumTexCoord * 2 * 4; for (DWORD i=0; i < dwNumTexCoord; i++) { dwTextureCoordSize[i] = 4*2; } } else { DWORD dwOffset = 0; dwTextureCoordSizeTotal = 0; for (DWORD i=0; i < dwNumTexCoord; i++) { BYTE dwSize = g_TextureSize[dwTextureFormats & 3]; dwTextureCoordSize[i] = dwSize; dwTextureCoordSizeTotal += dwSize; dwTextureFormats >>= 2; } } return dwTextureCoordSizeTotal; } //--------------------------------------------------------------------- // Computes vertex in bytes for the given FVF // inline DWORD ComputeVertexSizeFVF(DWORD dwFVF) { DWORD dwTextureFormats = dwFVF >> 16; DWORD dwNumTexCoord = FVF_TEXCOORD_NUMBER(dwFVF); DWORD size = GetVertexSizeFVF(dwFVF); if (dwTextureFormats == 0) { size += (BYTE)dwNumTexCoord * 2 * 4; } else { for (DWORD i=0; i < dwNumTexCoord; i++) { size += g_TextureSize[dwTextureFormats & 3]; dwTextureFormats >>= 2; } } return size; } //--------------------------------------------------------------------- // Computes the number of primtives and also updates the stats accordingly // Input: lpDevI->primType // dwNumVertices // Output: lpDevI->dwNumPrimitives // return value = dwNumPrimitives #undef DPF_MODNAME #define DPF_MODNAME "GetNumPrim" inline __declspec(nothrow) void GetNumPrim(LPD3DHAL lpDevI, DWORD dwNumVertices) { D3DFE_PROCESSVERTICES* pv = lpDevI->m_pv; pv->dwNumPrimitives = 0; switch (pv->primType) { case D3DPT_POINTLIST: pv->dwNumPrimitives = dwNumVertices; break; case D3DPT_LINELIST: pv->dwNumPrimitives = dwNumVertices >> 1; break; case D3DPT_LINESTRIP: if (dwNumVertices < 2) return; pv->dwNumPrimitives = dwNumVertices - 1; break; case D3DPT_TRIANGLEFAN: case D3DPT_TRIANGLESTRIP: if (dwNumVertices < 3) return; pv->dwNumPrimitives = dwNumVertices - 2; break; case D3DPT_TRIANGLELIST: #ifdef _X86_ { DWORD tmp; __asm { mov eax, 0x55555555 // fractional part of 1.0/3.0 mul dwNumVertices add eax, 0x80000000 // Rounding adc edx, 0 mov tmp, edx } pv->dwNumPrimitives = tmp; } #else pv->dwNumPrimitives = dwNumVertices / 3; #endif break; } } //--------------------------------------------------------------------- // Sets front-end flags every time fog state is changed // inline void CD3DHal::SetFogFlags(void) { // Call ForceFVFRecompute only if fog enable state has been changed BOOL bFogWasEnabled = m_pv->dwDeviceFlags & D3DDEV_FOG; if (m_pv->lighting.fog_mode != D3DFOG_NONE && this->rstates[D3DRENDERSTATE_FOGENABLE]) { m_pv->dwDeviceFlags |= D3DDEV_FOG; if (!bFogWasEnabled) ForceFVFRecompute(); } else { m_pv->dwDeviceFlags &= ~D3DDEV_FOG; if (bFogWasEnabled) ForceFVFRecompute(); } } //----------------------------------------------------------------------------- // Computes dwFlags bits which depend on the output FVF // inline void UpdateFlagsForOutputFVF(D3DFE_PROCESSVERTICES* lpDevI) { if (lpDevI->dwDeviceFlags & D3DDEV_LIGHTING && lpDevI->dwVIDOut & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR)) { lpDevI->dwFlags |= D3DPV_LIGHTING; } if (lpDevI->dwDeviceFlags & D3DDEV_FOG && lpDevI->dwVIDOut & D3DFVF_SPECULAR) { lpDevI->dwFlags |= D3DPV_FOG; } if (!(lpDevI->dwVIDOut & D3DFVF_DIFFUSE)) lpDevI->dwFlags |= D3DPV_DONOTCOPYDIFFUSE; if (!(lpDevI->dwVIDOut & D3DFVF_SPECULAR)) lpDevI->dwFlags |= D3DPV_DONOTCOPYSPECULAR; } //--------------------------------------------------------------------- // Restore indices in the texture stages which were re-mapped for texture // transforms // We have to do restore if // - Set or Get render state is issued with _WRAP parameter // - Set or Get texture stage is issued with TEXCOORDINDEX as a parameter // extern void RestoreTextureStages(LPD3DHAL pDevI); //--------------------------------------------------------------------- // the function works when there are texture transforms. // It computes number of output texture coordinates, texture coordinate size and format. // It prepares texture stages to re-map texture coordinates // void EvalTextureTransforms(LPD3DHAL pDevI, DWORD dwTexTransform, DWORD *pdwOutTextureSize, DWORD *pdwOutTextureFormat); //---------------------------------------------------------------------- // Sets texture transform pointer for every input texture coordinate set // void SetupTextureTransforms(LPD3DHAL pDevI); //---------------------------------------------------------------------- inline BOOL TextureTransformEnabled(LPD3DHAL pDevI) { return __TEXTURETRANSFORMENABLED(pDevI->m_pv); } //----------------------------------------------------------------------------- // Having primitive type as index, this array returns two coefficients("a" and // "b") to compute number of vertices as NumPrimitives*a + b // extern DWORD g_PrimToVerCount[7][2]; //----------------------------------------------------------------------------- inline UINT GETVERTEXCOUNT(D3DPRIMITIVETYPE primType, UINT dwNumPrimitives) { return g_PrimToVerCount[primType][0] * dwNumPrimitives + g_PrimToVerCount[primType][1]; } extern void setIdentity(D3DMATRIXI * m); extern void MatrixProduct(D3DMATRIXI *d, D3DMATRIXI *a, D3DMATRIXI *b); extern LIGHT_VERTEX_FUNC_TABLE lightVertexTable; extern void MatrixProduct(D3DMATRIXI *result, D3DMATRIXI *a, D3DMATRIXI *b); void D3DFE_UpdateLights(LPD3DHAL lpDevI); //--------------------------------------------------------------------- // Updates lighting and computes process vertices flags // extern void DoUpdateState(LPD3DHAL lpDevI); //---------------------------------------------------------------------- inline void UpdateClipStatus(CD3DHal* pDev) { pDev->m_ClipStatus.ClipUnion |= pDev->m_pv->dwClipUnion; pDev->m_ClipStatus.ClipIntersection &= pDev->m_pv->dwClipIntersection; } //---------------------------------------------------------------------- // This is a list of all rstates that which are for the vertex processing only. // In the software vertex processing mode these render states are not passed // to the driver. The are passed when we switch to the hardware vertex processing mode // const D3DRENDERSTATETYPE rsVertexProcessingList[] = { D3DRS_RANGEFOGENABLE, D3DRS_LIGHTING, D3DRS_AMBIENT, D3DRS_FOGVERTEXMODE, D3DRS_COLORVERTEX, D3DRS_LOCALVIEWER, D3DRS_NORMALIZENORMALS, D3DRS_DIFFUSEMATERIALSOURCE, D3DRS_SPECULARMATERIALSOURCE, D3DRS_AMBIENTMATERIALSOURCE, D3DRS_EMISSIVEMATERIALSOURCE, D3DRS_VERTEXBLEND, D3DRS_CLIPPLANEENABLE, D3DRS_SOFTWAREVERTEXPROCESSING, D3DRS_POINTSCALEENABLE, D3DRS_POINTSCALE_A, D3DRS_POINTSCALE_B, D3DRS_POINTSCALE_C, D3DRS_INDEXEDVERTEXBLENDENABLE, D3DRS_TWEENFACTOR }; #endif _DRAWPRIM_H_