📄 vgplite.c
字号:
/*****************************************************************************
Name : vgp.c
Title : VGP lite specific functions
C Author : Imagination Technologies
Created : 22/4/2004
Copyright : 2004 by Imagination Technologies Limited. All rights reserved.
No part of this software, either material or conceptual
may be copied or distributed, transmitted, transcribed,
stored in a retrieval system or translated into any
human or computer language in any form by any means,
electronic, mechanical, manual or other-wise, or
disclosed to third parties without the express written
permission of Imagination Technologies Limited, HomePark
Industrial Estate, King's Langley, Hertfordshire,
WD4 8LZ, U.K.
Description : VGP lite specific functions
Program Type : 32-bit DLL
Version : $Revision: 1.2 $
Modifications :
$Log: vgplite.c $
Initial revision
*****************************************************************************/
#include "context.h"
#if defined(SUPPORT_VGP_LITE)
/*****************************************************************************
* Include code sections
*****************************************************************************/
#include "vgpsections.c"
/*****************************************************************************/
/*****************************************************************************
FUNCTION : VGPTNLUpdateFFTNLShader
PURPOSE : Configures the fixed-function TNL vertex-shader according the
the current TN: requirements and state
PARAMETERS : psContext - The current 3D rendering context
RETURNS : void
****************************************************************************/
void VGPTNLUpdateFFTNLShader(LPD3DM_CONTEXT psContext)
{
PTRANSIENT_STATE psTState;
PSWTNLSTATE psSWTNLState;
DWORD dwTNLFlags;
DWORD dwTNLFlags2;
DWORD dwSectionModFlags;
DWORD dwRSFlags;
DWORD dwSectionStart;
DWORD dwSectionEnd;
DWORD dwSectionsToEnable;
DWORD dwTcCount;
DWORD dwBaseInstruction;
DWORD dwCurrentInstruction;
DWORD i;
HWVGPINST *pInstBuffer;
pInstBuffer = (HWVGPINST*) &psContext->sHWState.sVGPCode;
psTState = &psContext->sTState;
psSWTNLState = &psTState->sSWTNLState;
dwTNLFlags = psSWTNLState->dwTNLFlags;
dwTNLFlags2 = psSWTNLState->dwTNLFlags2;
dwSectionModFlags = psSWTNLState->dwSectionModFlags;
dwRSFlags = psTState->dwRSFlags;
/* Start by disabling all sections */
DisableSections(0xFFFFFFFF, psContext);
dwSectionsToEnable = 0;
/* Enable Position section */
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_POSITION;
if(dwSectionModFlags & (1 << VGPTNL_SECTIONORD_POSITION))
{
if(psContext->sTState.sSWTNLState.dwSectionModFlags & PVRD3DTNL_FLAGS_PASSTHROUGH_LOADED)
{
PVSINSTRANGE psExeRange = &psContext->sTState.sSWTNLState.psPTSectionMods[VGPTNL_SECTIONORD_POSITION].sExeRange;
/* The only change is the passthrough has been loaded, so we only need replace 1 instruction */
pInstBuffer[psExeRange->dwFirst] =
psContext->sTState.sSWTNLState.psPTSectionMods[VGPTNL_SECTIONORD_POSITION].psInstructions[0];
/* Set executable range */
SetSectionExeRange(VGPTNL_SECTIONORD_POSITION,
psExeRange->dwFirst,
psExeRange->dwLast,
psContext);
/* Flag modified instructions */
FlagArraySetFlagRange((PFLAGARRAY)&psContext->sHWStateCtl.sVGPInstsChanged,
psExeRange->dwFirst,
psExeRange->dwFirst);
}
else
{
/* Get position section first instruction address */
dwBaseInstruction = psContext->ppsFFTNLSections[VGPTNL_SECTIONORD_POSITION]->sConfig.sLoadRange.dwFirst;
dwCurrentInstruction = dwBaseInstruction;
/*
Setup the position section. Available sections: -
psPositionPassthruSection - Pass through input to output
psPositionZBiasPassthruSection - Add Z bias to Z and store in R0
psPositionWBiasPassthruSection - Add Z bias to W and store in R0
psPositionTransformSection - Transform postition and store in R0
psPositionZBiasSection - Add inverse VPTTrans of Z bias to Z (from R0) store in R0
psPositionWBiasSection - Add 1/(1/W + Z-bias) to W (from R0) store in R0
psPositionViewPortTransformSection - Does VPort transform for procvert mode
psPositionOutputSection - Move R0 to outputs
psPositionClipSection - Set front and rear clips
*/
if((psContext->psVertexSource->dwFVFFlags & D3DMFVF_POSITION_MASK) ==D3DMFVF_XYZRHW_FIXED ||
(psContext->psVertexSource->dwFVFFlags & D3DMFVF_POSITION_MASK) ==D3DMFVF_XYZRHW_FLOAT)
{
if(dwRSFlags & TSTATE_RSFLAGS_DEPTHBIAS)
{
if(psContext->dwTAPrimCtl & MBX1_TAPRIM_WBUFFERING_ENABLE)
{
/* Add Zbias to W */
for(i = 0; i < INSTCOUNT(psPositionWBiasPassthruSection); i++)
{
pInstBuffer[dwCurrentInstruction++] = psPositionWBiasPassthruSection[i];
}
}
else
{
/* Add Zbias to Z */
for(i = 0; i < INSTCOUNT(psPositionZBiasPassthruSection); i++)
{
pInstBuffer[dwCurrentInstruction++] = psPositionZBiasPassthruSection[i];
}
}
/* Copy to outputs */
pInstBuffer[dwCurrentInstruction++] = psPositionOutputSection[0];
}
else
{
/* Pass inputs to outputs */
pInstBuffer[dwCurrentInstruction++] = psPositionPassthruSection[0];
}
}
else
{
/* Add position transform */
for(i = 0; i < INSTCOUNT(psPositionTransformSection); i++)
{
pInstBuffer[dwCurrentInstruction++] = psPositionTransformSection[i];
}
/* Check for Depth bias */
if(dwRSFlags & TSTATE_RSFLAGS_DEPTHBIAS)
{
if(psContext->dwTAPrimCtl & MBX1_TAPRIM_WBUFFERING_ENABLE)
{
/* Add Zbias to W */
for(i = 0; i < INSTCOUNT(psPositionWBiasSection); i++)
{
pInstBuffer[dwCurrentInstruction++] = psPositionWBiasSection[i];
}
}
else
{
/* Add Zbias to Z */
for(i = 0; i < INSTCOUNT(psPositionZBiasSection); i++)
{
pInstBuffer[dwCurrentInstruction++] = psPositionZBiasSection[i];
}
}
}
/* If were in process vertices mode we'll need the viewport transform section */
if(psContext->dwFlags & D3DM_CONTEXT_SWFLAGS_PROCVERT_MODE)
{
/* Add Vport Xform section */
for(i = 0; i < INSTCOUNT(psPositionWBiasSection); i++)
{
pInstBuffer[dwCurrentInstruction++] = psPositionViewPortTransformSection[i];
}
}
/* Copy R0 to outputs */
pInstBuffer[dwCurrentInstruction++] = psPositionOutputSection[0];
if(dwRSFlags & TSTATE_RSFLAGS_CLIPPING)
{
/* Set front and rear clip */
for(i = 0; i < INSTCOUNT(psPositionClipSection); i++)
{
pInstBuffer[dwCurrentInstruction++] = psPositionClipSection[i];
}
}
}
/* Set executable range */
SetSectionExeRange(VGPTNL_SECTIONORD_POSITION,
dwBaseInstruction,
dwCurrentInstruction - 1,
psContext);
/* Flag modified instructions */
FlagArraySetFlagRange((PFLAGARRAY)&psContext->sHWStateCtl.sVGPInstsChanged,
dwBaseInstruction,
dwCurrentInstruction - 1);
}
dwSectionModFlags &= ~(1 << VGPTNL_SECTIONORD_POSITION);
}
/* FIXME: Output the specular directly if it is not calculated by the lighting code */
/* Set up the transform of the position and normal into camera space */
if(((dwRSFlags & TSTATE_RSFLAGS_LIGHTING) && (dwTNLFlags & PVRD3DTNL_FLAGS_ENABLED)) ||
(dwTNLFlags2 & PVRD3DTNL_FLAGS2_TEXGEN_NEEDPOSITION) ||
(dwTNLFlags2 & PVRD3DTNL_FLAGS2_TEXGEN_NEEDNORMAL) ||
(dwRSFlags & TSTATE_RSFLAGS_FOG))
{
/* Enable the position/normal object->view space transform */
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_POSTOVIEW;
if((dwTNLFlags2 & PVRD3DTNL_FLAGS2_TEXGEN_NEEDNORMAL) ||
((dwRSFlags & TSTATE_RSFLAGS_LIGHTING) && (dwTNLFlags & PVRD3DTNL_FLAGS_ENABLED)))
{
/* Also perform normal-vector normalisation if required */
dwSectionStart = 0;
if (dwRSFlags & TSTATE_RSFLAGS_NORMALIZENORMALS)
{
dwSectionEnd = SECTION_POSTOVIEW_NORMALISENORMAL_SIZE - 1;
}
else
{
dwSectionEnd = SECTION_POSTOVIEW_NORMAL_SIZE - 1;
}
}
else
{
/* We need the view position only for texgen or fog purposes */
dwSectionEnd = SECTION_POSTOVIEW_BASE_SIZE - 1;
}
SetSectionExeRange(VGPTNL_SECTIONORD_POSTOVIEW,
dwSectionStart,
dwSectionEnd,
psContext);
}
/*
Enable local viewer setup as appropriate
*/
if(((dwRSFlags & TSTATE_RSFLAGS_LIGHTING) && (dwTNLFlags & PVRD3DTNL_FLAGS_ENABLED)) ||
(dwTNLFlags2 & PVRD3DTNL_FLAGS2_TEXGEN_NEEDLOCALVIEWER))
{
if (dwRSFlags & TSTATE_RSFLAGS_LOCALVIEWER)
{
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_LVIEWERSETUPFROMVERTEX;
}
else
{
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_LVIEWERSETUPFROMDEFAULT;
}
}
/*
Lighting enabled?
*/
if((dwRSFlags & TSTATE_RSFLAGS_LIGHTING) &&
(dwTNLFlags & PVRD3DTNL_FLAGS_ENABLED))
{
DWORD dwColourSourceIndex, dwColourSourceBaseInstruction;
DWORD pdwSources[3];
DWORD i;
/*
Enable the lighting colour-source selection section
*/
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_COLOURSOURCESETUP;
/*
Configure the section to select the appropriate colours
NB: The code is arranged as 27 intruction triples, providing all
possible combinations of the colour-source selections for the
ambient, diffuse and specular lighting colours (emissive is
handled differently). We use the required colour-sources to
choose the appropriate three-instructions to execute.
*/
pdwSources[0] = (DWORD)psSWTNLState->sColourSourcesReq[TNLCOLSRCTYPE_AMBIENT];
pdwSources[1] = (DWORD)psSWTNLState->sColourSourcesReq[TNLCOLSRCTYPE_DIFFUSE];
pdwSources[2] = (DWORD)psSWTNLState->sColourSourcesReq[TNLCOLSRCTYPE_SPECULAR];
dwColourSourceIndex = (pdwSources[0] * 9) +
(pdwSources[1] * 3) +
(pdwSources[2] * 1);
/* Select instruction triplet */
dwColourSourceIndex *= 3;
/* Get first instruction address */
dwColourSourceBaseInstruction = psContext->ppsFFTNLSections[VGPTNL_SECTIONORD_COLOURSOURCESETUP]->sConfig.sLoadRange.dwFirst;
/* Write new instructions to state buffer */
for(i=0; i < psContext->ppsFFTNLSections[VGPTNL_SECTIONORD_COLOURSOURCESETUP]->dwInstCount; i++)
{
pInstBuffer[dwColourSourceBaseInstruction + i] = psColourSourceSectionPrototype[dwColourSourceIndex++];
}
/* Flag modified instructions */
FlagArraySetFlagRange((PFLAGARRAY)&psContext->sHWStateCtl.sVGPInstsChanged, dwColourSourceBaseInstruction, dwColourSourceBaseInstruction + 2);
/*
Any point lights enabled?
*/
if(psSWTNLState->dwLightCount > 0)
{
/* Enable the setup and lighting section */
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_LIGHTINGINIT;
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_GENERICLIGHT;
/*
Setup the execution-range to perform basic (diffuse+ambient)
calculation, plus (optionally) the specular part if required.
*/
dwSectionStart = 0;
if(dwRSFlags & TSTATE_RSFLAGS_SPECULAR)
{
dwSectionEnd = SECTION_GENERICLIGHT_SPECULAR_SIZE - 1;
}
else
{
dwSectionEnd = SECTION_GENERICLIGHT_BASE_SIZE - 1;
}
SetSectionExeRange(VGPTNL_SECTIONORD_GENERICLIGHT,
dwSectionStart,
dwSectionEnd,
psContext);
/*
Execute the section once for each enabled point light
*/
SetSectionRepeat(VGPTNL_SECTIONORD_GENERICLIGHT,
psSWTNLState->dwLightCount,
psContext);
}
/*
Finally: output the calculated colours (always output diffuse,
specular is optional)
*/
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_COLOUROUTPUT;
dwSectionStart = 0;
if(dwRSFlags & TSTATE_RSFLAGS_SPECULAR)
{
dwSectionEnd = SECTION_COLOUROUTPUT_FULL_SIZE - 1;
}
else
{
dwSectionEnd = SECTION_COLOUROUTPUT_DIFFUSEONLY_SIZE - 1;
}
SetSectionExeRange(VGPTNL_SECTIONORD_COLOUROUTPUT,
dwSectionStart,
dwSectionEnd,
psContext);
}
else
{
DWORD dwColoursPresent;
/*
Configure and enable setting-up of vertex-colour defaults (only if
both vertex colours are not present)
*/
dwColoursPresent = dwTNLFlags & (PVRD3DTNL_FLAGS_DIFFUSE_PRESENT |
PVRD3DTNL_FLAGS_SPECULAR_PRESENT);
if(dwColoursPresent != (PVRD3DTNL_FLAGS_DIFFUSE_PRESENT |
PVRD3DTNL_FLAGS_SPECULAR_PRESENT))
{
/*
Enable the default-colour setup section
*/
dwSectionsToEnable |= 1 << VGPTNL_SECTIONORD_COLOURSETDEFAULTS;
/*
Setup the section execution range to only set the default for the
colour components that are not present
*/
if(dwColoursPresent & PVRD3DTNL_FLAGS_DIFFUSE_PRESENT)
{
dwSectionStart = 1;
}
else
{
dwSectionStart = 0;
}
if (dwColoursPresent & PVRD3DTNL_FLAGS_SPECULAR_PRESENT)
{
dwSectionEnd = 0;
}
else
{
dwSectionEnd = 1;
}
SetSectionExeRange(VGPTNL_SECTIONORD_COLOURSETDEFAULTS,
dwSectionStart,
dwSectionEnd,
psContext);
}
/*
Lighting disabled
*/
if(dwColoursPresent)
{
/*
Enable the colour passthrough section
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -