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