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.
317 lines
11 KiB
317 lines
11 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: drawprim.hpp
|
|
* Content: DrawPrimitive common defines
|
|
*
|
|
***************************************************************************/
|
|
|
|
#ifndef _DRAWPRIM_H_
|
|
#define _DRAWPRIM_H_
|
|
|
|
#define MAX_DX6_PRIMCOUNT D3DMAXNUMPRIMITIVES
|
|
#define MAX_DX6_VERTICES D3DMAXNUMVERTICES
|
|
#ifdef WIN95
|
|
#define LOWVERTICESNUMBER 128
|
|
#else
|
|
#define LOWVERTICESNUMBER 96
|
|
#endif
|
|
#define D3D_MAX_TLVBUF_CHANGES 5
|
|
|
|
extern HRESULT DoDrawPrimitive(LPD3DFE_PROCESSVERTICES pv);
|
|
extern HRESULT DoDrawIndexedPrimitive(LPD3DFE_PROCESSVERTICES pv);
|
|
extern HRESULT CheckDrawPrimitive(LPDIRECT3DDEVICEI lpDevI);
|
|
extern HRESULT CheckDrawIndexedPrimitive(LPDIRECT3DDEVICEI lpDevI, DWORD dwStartVertex = 0);
|
|
|
|
// 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_DRIVERSUPPORTED(lpDevI) (lpDevI->dwDeviceFlags & D3DDEV_FVF)
|
|
#define FVF_TEXCOORD_NUMBER(dwFVF) \
|
|
(((dwFVF) & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT)
|
|
//----------------------------------------------------------------------
|
|
inline DWORD MakeTexTransformFuncIndex(DWORD dwNumInpTexCoord, DWORD dwNumOutTexCoord)
|
|
{
|
|
DDASSERT(dwNumInpTexCoord <= 4 && dwNumOutTexCoord <= 4);
|
|
return (dwNumInpTexCoord - 1) + ((dwNumOutTexCoord - 1) << 2);
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// The function should not be called by ProcessVertices!!!
|
|
//
|
|
// Computes nOutTexCoord, dwTextureCoordSizeTotal, dwTextureCoordSize and
|
|
// dwTextureIndexToCopy in case when a pre-DX6 driver is used.
|
|
//
|
|
void ComputeTCI2CopyLegacy(LPDIRECT3DDEVICEI lpDevI,
|
|
DWORD dwNumInpTexCoord,
|
|
DWORD* pdwInpTexCoordSize,
|
|
BOOL bVertexTransformed);
|
|
//---------------------------------------------------------------------
|
|
// 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_RESERVED1)
|
|
size += 4;
|
|
|
|
if (fvf & D3DFVF_DIFFUSE)
|
|
size+= 4;
|
|
if (fvf & D3DFVF_SPECULAR)
|
|
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;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CheckDeviceSettings"
|
|
inline HRESULT CheckDeviceSettings(LPDIRECT3DDEVICEI lpDevI)
|
|
{
|
|
#if DBG
|
|
if (!(lpDevI->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE))
|
|
{
|
|
D3D_ERR( "Not in scene" );
|
|
return D3DERR_SCENE_NOT_IN_SCENE;
|
|
}
|
|
#endif
|
|
return D3D_OK;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// 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(LPDIRECT3DDEVICEI lpDevI, DWORD dwNumVertices)
|
|
{
|
|
lpDevI->dwNumPrimitives = 0;
|
|
switch (lpDevI->primType)
|
|
{
|
|
case D3DPT_POINTLIST:
|
|
lpDevI->dwNumPrimitives = dwNumVertices;
|
|
break;
|
|
case D3DPT_LINELIST:
|
|
lpDevI->dwNumPrimitives = dwNumVertices >> 1;
|
|
break;
|
|
case D3DPT_LINESTRIP:
|
|
if (dwNumVertices < 2)
|
|
return;
|
|
lpDevI->dwNumPrimitives = dwNumVertices - 1;
|
|
break;
|
|
case D3DPT_TRIANGLEFAN:
|
|
case D3DPT_TRIANGLESTRIP:
|
|
if (dwNumVertices < 3)
|
|
return;
|
|
lpDevI->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
|
|
}
|
|
lpDevI->dwNumPrimitives = tmp;
|
|
}
|
|
#else
|
|
lpDevI->dwNumPrimitives = dwNumVertices / 3;
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// Sets front-end flags every time fog state is changed
|
|
//
|
|
inline void DIRECT3DDEVICEI::SetFogFlags(void)
|
|
{
|
|
// Call ForceFVFRecompute only if fog enable state has been changed
|
|
BOOL bFogWasEnabled = this->dwDeviceFlags & D3DDEV_FOG;
|
|
if (this->lighting.fog_mode != D3DFOG_NONE &&
|
|
this->rstates[D3DRENDERSTATE_FOGENABLE])
|
|
{
|
|
this->dwDeviceFlags |= D3DDEV_FOG;
|
|
if (!bFogWasEnabled)
|
|
ForceFVFRecompute();
|
|
}
|
|
else
|
|
{
|
|
this->dwDeviceFlags &= ~D3DDEV_FOG;
|
|
if (bFogWasEnabled)
|
|
ForceFVFRecompute();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// Validates DrawPrimitive flags
|
|
//
|
|
inline BOOL IsDPFlagsValid(DWORD dwFlags)
|
|
{
|
|
if (dwFlags & ~(D3DDP_WAIT))
|
|
{
|
|
D3D_ERR( "Invalid bit set in DrawPrimitive flags" );
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
inline void RestoreTextureStages(LPDIRECT3DDEVICEI pDevI)
|
|
{
|
|
// dwVIDIn is used to force re-compute FVF in the
|
|
// SetTextureStageState. so we save and restore it.
|
|
DWORD dwVIDInSaved = pDevI->dwVIDIn;
|
|
pDevI->dwDeviceFlags &= ~D3DDEV_REMAPTEXTUREINDICES;
|
|
for (DWORD i=0; i < pDevI->dwNumTextureStages; i++)
|
|
{
|
|
LPD3DFE_TEXTURESTAGE pStage = &pDevI->textureStage[i];
|
|
// Texture generation mode was stripped out of pStage->dwInpCoordIndex
|
|
DWORD dwInpIndex = pStage->dwInpCoordIndex + pStage->dwTexGenMode;
|
|
if (dwInpIndex != pStage->dwOutCoordIndex)
|
|
{
|
|
// We do not call UpdateInternalTextureStageState because it
|
|
// will call ForceRecomputeFVF and we do not want this.
|
|
pDevI->tsstates[pStage->dwOrgStage][D3DTSS_TEXCOORDINDEX] = dwInpIndex;
|
|
|
|
// Filter texgen modes for DX6 drivers
|
|
if (!IS_TLHAL_DEVICE(pDevI) && dwInpIndex > 7)
|
|
continue;
|
|
|
|
CDirect3DDeviceIDP2 *pDevDP2 = static_cast<CDirect3DDeviceIDP2*>(pDevI);
|
|
pDevDP2->SetTSSI(pStage->dwOrgStage, D3DTSS_TEXCOORDINDEX, dwInpIndex);
|
|
}
|
|
DWORD dwState = D3DRENDERSTATE_WRAP0 + pStage->dwOutCoordIndex;
|
|
if (pStage->dwOrgWrapMode != pDevI->rstates[dwState])
|
|
{
|
|
// We do not call UpdateInternaState because it
|
|
// will call ForceRecomputeFVF and we do not want this.
|
|
pDevI->rstates[dwState] = pStage->dwOrgWrapMode;
|
|
pDevI->SetRenderStateI((D3DRENDERSTATETYPE)dwState, pStage->dwOrgWrapMode);
|
|
}
|
|
}
|
|
pDevI->dwVIDIn = dwVIDInSaved;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
// 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
|
|
//
|
|
HRESULT EvalTextureTransforms(LPDIRECT3DDEVICEI pDevI, DWORD dwTexTransform,
|
|
DWORD *pdwOutTextureSize, DWORD *pdwOutTextureFormat);
|
|
//----------------------------------------------------------------------
|
|
// Sets texture transform pointer for every input texture coordinate set
|
|
//
|
|
void SetupTextureTransforms(LPDIRECT3DDEVICEI pDevI);
|
|
//----------------------------------------------------------------------
|
|
inline BOOL TextureTransformEnabled(LPDIRECT3DDEVICEI pDevI)
|
|
{
|
|
return __TEXTURETRANSFORMENABLED(pDevI);
|
|
}
|
|
//---------------------------------------------------------------------
|
|
inline void ComputeOutputVertexOffsets(LPD3DFE_PROCESSVERTICES pv)
|
|
{
|
|
DWORD i = 4*sizeof(D3DVALUE);
|
|
pv->diffuseOffsetOut = i;
|
|
if (pv->dwVIDOut & D3DFVF_DIFFUSE)
|
|
i += sizeof(DWORD);
|
|
pv->specularOffsetOut = i;
|
|
if (pv->dwVIDOut & D3DFVF_SPECULAR)
|
|
i += sizeof(DWORD);
|
|
pv->texOffsetOut = i;
|
|
}
|
|
|
|
#endif _DRAWPRIM_H_
|