Leaked source code of windows server 2003
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.
 
 
 
 
 
 

309 lines
9.9 KiB

//----------------------------------------------------------------------------
//
// primproc.cpp
//
// Miscellaneous PrimProcessor methods.
//
// Copyright (C) Microsoft Corporation, 1997.
//
//----------------------------------------------------------------------------
#include "rgb_pch.h"
#pragma hdrstop
#include "d3dutil.h"
#include "setup.hpp"
#include "attrs_mh.h"
#include "tstp_mh.h"
#include "walk_mh.h"
#include "rsdbg.hpp"
DBG_DECLARE_FILE();
//----------------------------------------------------------------------------
//
// PrimProcessor::BeginPrimSet
//
// Marks the start of a set of primitives that have the same vertex type.
// Computes attributes used from the current state and the vertex type.
//
//----------------------------------------------------------------------------
void
PrimProcessor::BeginPrimSet(D3DPRIMITIVETYPE PrimType,
RAST_VERTEX_TYPE VertType)
{
// If state hasn't changed and the primitive and vertex types match the
// ones we're already set up for there's no work to do.
if ((m_uPpFlags & PPF_STATE_CHANGED) == 0 &&
VertType == m_VertType &&
PrimType == m_PrimType)
{
return;
}
m_StpCtx.uFlags &= ~PRIMSF_ALL;
if (m_StpCtx.pCtx->pdwRenderState[D3DRS_ZENABLE] ||
m_StpCtx.pCtx->pdwRenderState[D3DRS_ZWRITEENABLE] ||
m_StpCtx.pCtx->pdwRenderState[D3DRS_STENCILENABLE])
{
m_StpCtx.uFlags |= PRIMSF_Z_USED;
}
/*if (m_StpCtx.pCtx->BeadSet == D3DIBS_RAMP)
{
// Index is unused during copy mode texturing.
if (m_StpCtx.pCtx->pdwRenderState
[D3DRENDERSTATE_TEXTUREMAPBLEND] != D3DTBLEND_COPY ||
m_StpCtx.pCtx->cActTex == 0)
{
m_StpCtx.uFlags |= PRIMSF_DIDX_USED;
}
}
else */
{
// ATTENTION - Don't set these for copy mode texture? Is
// copy mode texture meaningful in RGB?
m_StpCtx.uFlags |= PRIMSF_DIFF_USED;
if (m_StpCtx.pCtx->pdwRenderState[D3DRS_SPECULARENABLE])
{
m_StpCtx.uFlags |= PRIMSF_SPEC_USED;
}
}
if (m_StpCtx.pCtx->pdwRenderState[D3DRS_SHADEMODE] ==
D3DSHADE_FLAT)
{
m_StpCtx.uFlags |= PRIMSF_FLAT_SHADED;
}
if (m_StpCtx.pCtx->cActTex > 0)
{
m_StpCtx.uFlags |= PRIMSF_TEX1_USED;
if (m_StpCtx.pCtx->cActTex > 1)
{
m_StpCtx.uFlags |= PRIMSF_TEX2_USED;
}
}
if ((m_StpCtx.uFlags & PRIMSF_TEX_USED) &&
(true || m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE]))
{
m_StpCtx.uFlags |= PRIMSF_PERSP_USED;
}
// Currently only tex1 can be mipmapped.
if (((m_StpCtx.uFlags & PRIMSF_TEX1_USED) &&
(PrimType == D3DPT_TRIANGLELIST ||
PrimType == D3DPT_TRIANGLESTRIP ||
PrimType == D3DPT_TRIANGLEFAN) &&
(m_StpCtx.pCtx->pdwRenderState[D3DRS_FILLMODE]
== D3DFILL_SOLID)) &&
(((m_StpCtx.pCtx->pTexture[0]->cLOD >= 1) &&
(m_StpCtx.pCtx->pTexture[0]->uMipFilter != D3DTFP_NONE)) ||
// need LOD if we need to dynamically switch between different min
// and mag filters
(m_StpCtx.pCtx->pTexture[0]->uMinFilter !=
m_StpCtx.pCtx->pTexture[0]->uMagFilter)))
{
m_StpCtx.uFlags |= PRIMSF_LOD_USED;
}
// select between min and mag filters for TEX2
if (((m_StpCtx.uFlags & PRIMSF_TEX2_USED) &&
(PrimType == D3DPT_TRIANGLELIST ||
PrimType == D3DPT_TRIANGLESTRIP ||
PrimType == D3DPT_TRIANGLEFAN) &&
(m_StpCtx.pCtx->pdwRenderState[D3DRS_FILLMODE]
== D3DFILL_SOLID)) &&
(((m_StpCtx.pCtx->pTexture[1]->cLOD >= 1) &&
(m_StpCtx.pCtx->pTexture[1]->uMipFilter != D3DTFP_NONE)) ||
// need LOD if we need to dynamically switch between different min
// and mag filters
(m_StpCtx.pCtx->pTexture[1]->uMinFilter !=
m_StpCtx.pCtx->pTexture[1]->uMagFilter)))
{
m_StpCtx.uFlags |= PRIMSF_LOD_USED;
}
if (m_StpCtx.pCtx->pdwRenderState[D3DRS_FOGENABLE])
{
// Note, if PWL_FOG is ever brought back to life, enabling
// PRIMSF_GLOBAL_FOG_USED with no Z buffer will not trivially work
// if (m_StpCtx.uFlags & PRIMSF_Z_USED)
{
switch (m_StpCtx.pCtx->pdwRenderState[D3DRS_FOGTABLEMODE])
{
case D3DFOG_EXP:
case D3DFOG_EXP2:
case D3DFOG_LINEAR:
m_StpCtx.uFlags |= PRIMSF_GLOBAL_FOG_USED;
#ifndef PWL_FOG
// The span routines don't support table fog directly.
// Instead table fog is computed per vertex and used to
// set up local fog.
m_StpCtx.uFlags |= PRIMSF_LOCAL_FOG_USED;
#endif
break;
default:
m_StpCtx.uFlags |= PRIMSF_LOCAL_FOG_USED;
break;
}
}
}
PFN_ADDATTRS *ppfnAddAttrsTable;
PFN_ADDSCALEDATTRS *ppfnAddScaledAttrsTable;
PFN_FILLSPANATTRS *ppfnFillSpanAttrsTable;
if (m_StpCtx.pCtx->BeadSet == D3DIBS_RAMP)
{
// Ramp does not support multitexture.
RSASSERT((m_StpCtx.uFlags & PRIMSF_TEX2_USED) == 0);
RSASSERT((PRIMSF_TEX1_USED | PRIMSF_DIDX_USED) == 0x14);
// Derive a function table index from bits 2 and 4 of usage
// information.
// An alternative method would be to use bits 0-4 and have the
// ramp information in the top 16 entries, but splitting the
// ramp and RGB tables is cleaner and decouples the table sizes.
// Decoupling is useful since the ramp possibilities are much
// more limited so its table can be smaller.
m_iAttrFnIdx =
((m_StpCtx.uFlags & PRIMSF_TEX1_USED) >> 2) |
((m_StpCtx.uFlags & PRIMSF_DIDX_USED) >> 3);
ppfnAddAttrsTable = g_pfnRampAddFloatAttrsTable;
ppfnAddScaledAttrsTable = g_pfnRampAddScaledFloatAttrsTable;
ppfnFillSpanAttrsTable = g_pfnRampFillSpanFloatAttrsTable;
}
else
{
RSASSERT((PRIMSF_DIFF_USED | PRIMSF_SPEC_USED | PRIMSF_TEX1_USED |
PRIMSF_TEX2_USED) == 0xf);
// Derive a function table index from the lower four bits of
// usage information. The lower bits are deliberately chosen
// to represent the more performance-sensitive cases while
// the upper bits generally represent cases handled by generic
// code.
//
// Even restricted to only four bits the index contains unimportant
// and unreachable cases, such as specular without diffuse or
// tex2 without tex1. Tables indexed must account for this.
m_iAttrFnIdx = m_StpCtx.uFlags & (PRIMSF_DIFF_USED | PRIMSF_SPEC_USED |
PRIMSF_TEX1_USED | PRIMSF_TEX2_USED);
ppfnAddAttrsTable = g_pfnAddFloatAttrsTable;
ppfnAddScaledAttrsTable = g_pfnAddScaledFloatAttrsTable;
ppfnFillSpanAttrsTable = g_pfnFillSpanFloatAttrsTable;
}
//
// These functions only depend on the index and so can be set here.
// Other functions depend on per-triangle information and are set
// later.
//
if ((m_StpCtx.uFlags & PRIMSF_SLOW_USED) != PRIMSF_Z_USED)
{
// If any slow attrs are on or Z is off use the general functions.
m_StpCtx.pfnAddScaledAttrs = AddScaledFloatAttrs_Any_Either;
#ifndef STEP_FIXED
m_StpCtx.pfnAddAttrs = AddFloatAttrs_Any;
m_StpCtx.pfnFillSpanAttrs = FillSpanFloatAttrs_Any_Either;
#endif
}
else
{
m_StpCtx.pfnAddScaledAttrs =
ppfnAddScaledAttrsTable[m_iAttrFnIdx];
#ifndef STEP_FIXED
m_StpCtx.pfnAddAttrs = ppfnAddAttrsTable[m_iAttrFnIdx];
m_StpCtx.pfnFillSpanAttrs = ppfnFillSpanAttrsTable[m_iAttrFnIdx];
#endif
}
// Attribute beads can be set here.
PFN_SETUPTRIATTR *ppfnSlot;
ppfnSlot = &m_StpCtx.pfnTriSetupFirstAttr;
if (m_StpCtx.uFlags & PRIMSF_Z_USED)
{
if (m_StpCtx.pCtx->iZBitCount == 16)
{
*ppfnSlot = TriSetup_Z16;
}
else
{
*ppfnSlot = TriSetup_Z32;
}
ppfnSlot = &m_StpCtx.pfnTriSetupZEnd;
}
if (m_StpCtx.uFlags & PRIMSF_TEX1_USED)
{
if (m_StpCtx.uFlags & PRIMSF_PERSP_USED)
{
*ppfnSlot = TriSetup_Persp_Tex;
}
else
{
*ppfnSlot = TriSetup_Affine_Tex;
}
ppfnSlot = &m_StpCtx.pfnTriSetupTexEnd;
}
if (m_StpCtx.uFlags & PRIMSF_DIFF_USED)
{
if (m_StpCtx.uFlags & PRIMSF_FLAT_SHADED)
{
*ppfnSlot = TriSetup_DiffFlat;
}
else
{
*ppfnSlot = TriSetup_Diff;
}
ppfnSlot = &m_StpCtx.pfnTriSetupDiffEnd;
}
else if (m_StpCtx.uFlags & PRIMSF_DIDX_USED)
{
if (m_StpCtx.uFlags & PRIMSF_FLAT_SHADED)
{
*ppfnSlot = TriSetup_DIdxFlat;
}
else
{
*ppfnSlot = TriSetup_DIdx;
}
ppfnSlot = &m_StpCtx.pfnTriSetupDiffEnd;
}
if (m_StpCtx.uFlags & PRIMSF_SPEC_USED)
{
if (m_StpCtx.uFlags & PRIMSF_FLAT_SHADED)
{
*ppfnSlot = TriSetup_SpecFlat;
}
else
{
*ppfnSlot = TriSetup_Spec;
}
ppfnSlot = &m_StpCtx.pfnTriSetupSpecEnd;
}
if (m_StpCtx.uFlags & PRIMSF_LOCAL_FOG_USED)
{
*ppfnSlot = TriSetup_Fog;
ppfnSlot = &m_StpCtx.pfnTriSetupFogEnd;
}
*ppfnSlot = TriSetup_End;
// Remember the primitive and vertex type and clear the state change bit.
m_PrimType = PrimType;
m_VertType = VertType;
m_uPpFlags &= ~PPF_STATE_CHANGED;
}