windows-nt/Source/XPSP1/NT/multimedia/directx/dxg/d3d8/fe/drawprim.hpp
2020-09-26 16:20:57 +08:00

322 lines
10 KiB
C++

/*==========================================================================;
*
* 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_