Files
Cesarus85--mjolnir-vr/libs/d3d8/combiner.cpp
T

794 lines
30 KiB
C++

/* January fixed-function register combiners.
* Adapted from the legacy combiner implementation in RXDK-Libs.
* Copyright 2026 Team Resurgent. SPDX-License-Identifier: GPL-3.0-or-later
* Reference commit 29e018674a3443f9df5b5cb4478bb9c54d8a2a3a.
* Original cachebeta code/PDB controls per-device storage, types and semantics.
* Valid domain: four texture stages, eight combiner stages, selectors A..D,
* initialized device and exclusive access to its texture-stage shadow state.
*/
#include "combiner_internal.h"
#pragma code_seg("D3D")
namespace D3D
{
/* Original writable shift table. Its private-data ownership remains unresolved
* in the extracted target; keep the authentic name rather than an address. */
static DWORD kelvinCombinerInputShift[4] = { 24, 16, 8, 0 };
void WINAPI nvKelvinACSetAlphaInputOne(
CDevice *pDevice,
kelvinCombinerInput eInput,
DWORD dwCombinerStage,
BOOL bNegate)
{
DWORD dwICW = 0;
dwICW |= bNegate ? PS_INPUTMAPPING_EXPAND_NORMAL : PS_INPUTMAPPING_UNSIGNED_INVERT;
pDevice->m_AlphaICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
return;
}
HRESULT WINAPI nvKelvinACSelectAlphaInput(
CDevice *pDevice,
kelvinCombinerInput eInput,
DWORD dwCombinerStage,
DWORD dwD3DStage,
DWORD dwD3DTSSArg,
BOOL bComplement,
BOOL bExpandNormal)
{
DWORD dwICW = 0;
switch (D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_SELECTMASK)
{
case D3DTA_CURRENT:
if (dwCombinerStage != 0)
{
dwICW |= PS_REGISTER_R0;
break;
}
/* Current in stage zero is incoming diffuse. */
case D3DTA_DIFFUSE:
dwICW |= PS_REGISTER_V0;
break;
case D3DTA_TEXTURE:
if (pDevice->m_Textures[dwD3DStage] == NULL)
return TSS_USES_NULL_TEXTURE;
dwICW |= (PS_REGISTER_T0 + dwD3DStage) & D3DTA_SELECTMASK;
break;
case D3DTA_TFACTOR:
dwICW |= PS_REGISTER_C0;
break;
case D3DTA_TEMP:
dwICW |= PS_REGISTER_R1;
break;
case D3DTA_SPECULAR:
dwICW |= PS_REGISTER_V1;
pDevice->m_StateFlags |= COMBINER_NEEDS_SPECULAR;
break;
default:
/* Original release behavior outside valid selectors. */
break;
}
dwICW |= PS_CHANNEL_ALPHA;
bComplement = ((D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_COMPLEMENT)
^ (bComplement ? D3DTA_COMPLEMENT : 0)) ? TRUE : FALSE;
if (bExpandNormal)
dwICW |= bComplement ? PS_INPUTMAPPING_EXPAND_NEGATE : PS_INPUTMAPPING_EXPAND_NORMAL;
else
dwICW |= bComplement ? PS_INPUTMAPPING_UNSIGNED_INVERT : PS_INPUTMAPPING_UNSIGNED_IDENTITY;
pDevice->m_AlphaICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
return S_OK;
}
static HRESULT WINAPI nvKelvinACSelect1(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACSelect2(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACModulate(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACAdd(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACSub(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputC, dwHWStage, TRUE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACAddSmooth(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, TRUE, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACBlendAlpha(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage,
DWORD dwType)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
DWORD dwTemp;
if (dwType == COMBINER_PREMULTIPLIED_TEXTURE)
{
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
dwType = D3DTA_TEXTURE;
}
else
{
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2];
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = dwType;
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = dwTemp;
}
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG1];
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG1] = dwType;
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, TRUE, FALSE);
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG1] = dwTemp;
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACPremodulate(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr;
if (dwHWStage == 0)
{
/* The original reads the next row without checking that it exists.
* Point-sprite stage remapping can supply texture stage three. Retain
* a bounded fallback rather than manufacturing that out-of-bounds read.
* This complete defensive draft is nonexact and receives zero credit. */
if (dwD3DStage < D3DTSS_MAXSTAGES - 1
&& D3D__TextureState[dwD3DStage + 1][D3DTSS_ALPHAOP] != D3DTOP_DISABLE)
{
hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
DWORD dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2];
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = D3DTA_TEXTURE;
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
D3D__TextureState[dwD3DStage][D3DTSS_ALPHAARG2] = dwTemp;
}
else
{
hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
}
else
{
hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
return hr;
}
static HRESULT WINAPI nvKelvinACMultiplyAdd(
CDevice *pDevice,
int dwHWStage,
int dwD3DStage)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG0, FALSE, FALSE);
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinACLerp(
CDevice *pDevice,
int dwHWStage,
int dwD3DStage)
{
HRESULT hr = nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG0, FALSE, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG1, FALSE, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG0, TRUE, FALSE);
hr |= nvKelvinACSelectAlphaInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_ALPHAARG2, FALSE, FALSE);
return hr;
}
void WINAPI nvConstructKelvinOutputAlphaCombiners(
CDevice *pDevice,
BOOL bEnable,
DWORD dwStage,
DWORD dwD3DStage,
BOOL bBias,
DWORD dwShift,
BOOL bOutTemp)
{
/* January does not clear ICW here, unlike the later reference. */
if (!bEnable || D3D__TextureState[dwD3DStage][D3DTSS_COLOROP] == D3DTOP_DOTPRODUCT3)
return;
switch (dwShift)
{
case COMBINER_SHIFT_NONE:
pDevice->m_AlphaOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_BIAS << 12) : (PS_COMBINEROUTPUT_IDENTITY << 12);
break;
case COMBINER_SHIFT_ONE:
pDevice->m_AlphaOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_1 << 12);
break;
case COMBINER_SHIFT_TWO:
pDevice->m_AlphaOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_2 << 12);
break;
default:
break;
}
pDevice->m_AlphaOCW[dwStage] |= PS_REGISTER_R0 << 8;
pDevice->m_AlphaOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 8) : (PS_REGISTER_R0 << 8);
return;
}
void WINAPI ConstructAlphaCombiners(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage,
BOOL bStageActive)
{
DWORD dwShift = 0;
BOOL bBias = FALSE;
BOOL bEnable = TRUE;
HRESULT hr = S_OK;
pDevice->m_AlphaICW[dwHWStage] = 0;
pDevice->m_AlphaOCW[dwHWStage] = 0;
if (!bStageActive)
{
if (dwHWStage == 0)
{
pDevice->m_AlphaICW[dwHWStage] |= (PS_REGISTER_V0 | PS_CHANNEL_ALPHA) << 24;
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
else
bEnable = FALSE;
}
else
{
switch (D3D__TextureState[dwD3DStage][D3DTSS_ALPHAOP])
{
default:
case D3DTOP_DOTPRODUCT3:
case D3DTOP_DISABLE:
if (dwHWStage == 0)
{
pDevice->m_AlphaICW[dwHWStage] |= (PS_REGISTER_V0 | PS_CHANNEL_ALPHA) << 24;
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
else
bEnable = FALSE;
break;
case D3DTOP_SELECTARG1:
hr = nvKelvinACSelect1(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_SELECTARG2:
hr = nvKelvinACSelect2(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_MODULATE4X:
dwShift++;
/* Each fallthrough adds one scaling bit. */
case D3DTOP_MODULATE2X:
dwShift++;
case D3DTOP_MODULATE:
hr = nvKelvinACModulate(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_ADDSIGNED2X:
dwShift = 1;
case D3DTOP_ADDSIGNED:
bBias = TRUE;
case D3DTOP_ADD:
hr = nvKelvinACAdd(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_SUBTRACT:
hr = nvKelvinACSub(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_ADDSMOOTH:
hr = nvKelvinACAddSmooth(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_BLENDDIFFUSEALPHA:
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_DIFFUSE);
break;
case D3DTOP_BLENDTEXTUREALPHA:
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TEXTURE);
break;
case D3DTOP_BLENDFACTORALPHA:
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TFACTOR);
break;
case D3DTOP_BLENDTEXTUREALPHAPM:
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, COMBINER_PREMULTIPLIED_TEXTURE);
break;
case D3DTOP_BLENDCURRENTALPHA:
hr = nvKelvinACBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_CURRENT);
break;
case D3DTOP_PREMODULATE:
hr = nvKelvinACPremodulate(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_MULTIPLYADD:
hr = nvKelvinACMultiplyAdd(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_LERP:
hr = nvKelvinACLerp(pDevice, dwHWStage, dwD3DStage);
break;
}
}
if (hr == TSS_USES_NULL_TEXTURE)
{
if (dwHWStage == 0)
pDevice->m_AlphaICW[dwHWStage] = (PS_REGISTER_V0 | PS_CHANNEL_ALPHA) << 24;
else
pDevice->m_AlphaICW[dwHWStage] = (PS_REGISTER_R0 | PS_CHANNEL_ALPHA) << 24;
nvKelvinACSetAlphaInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
nvConstructKelvinOutputAlphaCombiners(pDevice, bEnable, dwHWStage, dwD3DStage, bBias, dwShift,
D3D__TextureState[dwD3DStage][D3DTSS_RESULTARG] == D3DTA_TEMP);
return;
}
void WINAPI nvKelvinCCSetColorInputOne(
CDevice *pDevice,
kelvinCombinerInput eInput,
DWORD dwCombinerStage,
BOOL bNegate)
{
DWORD dwICW = 0;
dwICW |= bNegate ? PS_INPUTMAPPING_EXPAND_NORMAL : PS_INPUTMAPPING_UNSIGNED_INVERT;
pDevice->m_ColorICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
return;
}
HRESULT WINAPI nvKelvinCCSelectColorInput(
CDevice *pDevice,
kelvinCombinerInput eInput,
DWORD dwCombinerStage,
DWORD dwD3DStage,
DWORD dwD3DTSSArg,
BOOL bComplement,
BOOL bExpandNormal,
BOOL bAlphaReplicate)
{
DWORD dwICW = 0;
switch (D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_SELECTMASK)
{
case D3DTA_CURRENT:
if (dwCombinerStage != 0)
{
dwICW |= PS_REGISTER_R0;
break;
}
/* Current in stage zero is incoming diffuse. */
case D3DTA_DIFFUSE:
dwICW |= PS_REGISTER_V0;
break;
case D3DTA_TEXTURE:
if (pDevice->m_Textures[dwD3DStage] == NULL)
return TSS_USES_NULL_TEXTURE;
dwICW |= (PS_REGISTER_T0 + dwD3DStage) & D3DTA_SELECTMASK;
break;
case D3DTA_TFACTOR:
dwICW |= PS_REGISTER_C0;
break;
case D3DTA_SPECULAR:
dwICW |= PS_REGISTER_V1;
pDevice->m_StateFlags |= COMBINER_NEEDS_SPECULAR;
break;
case D3DTA_TEMP:
dwICW |= PS_REGISTER_R1;
break;
default:
/* Original release behavior outside valid selectors. */
break;
}
bAlphaReplicate |= D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_ALPHAREPLICATE;
dwICW |= bAlphaReplicate ? PS_CHANNEL_ALPHA : PS_CHANNEL_RGB;
bComplement = ((D3D__TextureState[dwD3DStage][dwD3DTSSArg] & D3DTA_COMPLEMENT)
^ (bComplement ? D3DTA_COMPLEMENT : 0)) ? TRUE : FALSE;
if (bExpandNormal)
dwICW |= bComplement ? PS_INPUTMAPPING_EXPAND_NEGATE : PS_INPUTMAPPING_EXPAND_NORMAL;
else
dwICW |= bComplement ? PS_INPUTMAPPING_UNSIGNED_INVERT : PS_INPUTMAPPING_UNSIGNED_IDENTITY;
pDevice->m_ColorICW[dwCombinerStage] |= dwICW << kelvinCombinerInputShift[eInput];
return S_OK;
}
static HRESULT WINAPI nvKelvinCCSelect1(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCSelect2(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCModulate(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCAdd(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputC, dwHWStage, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCSub(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputC, dwHWStage, TRUE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCAddSmooth(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, TRUE, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCBlendAlpha(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage,
DWORD dwType)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
DWORD dwTemp;
if (dwType == COMBINER_PREMULTIPLIED_TEXTURE)
{
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
dwType = D3DTA_TEXTURE;
}
else
{
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2];
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = dwType;
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, TRUE);
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = dwTemp;
}
dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1];
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = dwType;
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, TRUE, FALSE, TRUE);
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = dwTemp;
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCPremodulate(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr;
if (dwHWStage == 0)
{
/* Color premodulation tests the fixed second texture row in January. */
if (D3D__TextureState[1][D3DTSS_COLOROP] != D3DTOP_DISABLE)
{
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
DWORD dwTemp = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2];
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = D3DTA_TEXTURE;
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG2] = dwTemp;
}
else
{
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
}
else
{
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
return hr;
}
static HRESULT WINAPI nvKelvinCCModulateAlpha(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage,
BOOL bComplement)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, bComplement, FALSE, TRUE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCModulateColor(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage,
BOOL bComplement)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, bComplement, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, TRUE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputD, dwHWStage, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinBumpMap(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr;
if (pDevice->m_Textures[dwD3DStage] == NULL)
hr = TSS_USES_NULL_TEXTURE;
else
{
DWORD dwArg1Cache = D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1];
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = D3DTA_CURRENT;
hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
D3D__TextureState[dwD3DStage][D3DTSS_COLORARG1] = dwArg1Cache;
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
return hr;
}
static HRESULT WINAPI nvKelvinCCDotProduct(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, TRUE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, TRUE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCMultiplyAdd(
CDevice *pDevice,
int dwHWStage,
int dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG0, FALSE, FALSE, FALSE);
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
static HRESULT WINAPI nvKelvinCCLerp(
CDevice *pDevice,
int dwHWStage,
int dwD3DStage)
{
HRESULT hr = nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputA, dwHWStage, dwD3DStage, D3DTSS_COLORARG0, FALSE, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputB, dwHWStage, dwD3DStage, D3DTSS_COLORARG1, FALSE, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputC, dwHWStage, dwD3DStage, D3DTSS_COLORARG0, TRUE, FALSE, FALSE);
hr |= nvKelvinCCSelectColorInput(pDevice, kelvinCombinerInputD, dwHWStage, dwD3DStage, D3DTSS_COLORARG2, FALSE, FALSE, FALSE);
return hr;
}
void WINAPI nvConstructKelvinOutputColorCombiners(
CDevice *pDevice,
BOOL bEnable,
DWORD dwStage,
BOOL bBias,
DWORD dwShift,
BOOL bDotAB,
BOOL bDotCD,
BOOL bOutTemp)
{
if (!bEnable)
return;
switch (dwShift)
{
case COMBINER_SHIFT_NONE:
pDevice->m_ColorOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_BIAS << 12) : (PS_COMBINEROUTPUT_IDENTITY << 12);
break;
case COMBINER_SHIFT_ONE:
pDevice->m_ColorOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_1 << 12);
break;
case COMBINER_SHIFT_TWO:
pDevice->m_ColorOCW[dwStage] |= bBias ? (PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS << 12) : (PS_COMBINEROUTPUT_SHIFTLEFT_2 << 12);
break;
default:
break;
}
if (bDotAB && bDotCD)
{
pDevice->m_ColorOCW[dwStage] |= (PS_COMBINEROUTPUT_AB_DOT_PRODUCT | PS_COMBINEROUTPUT_CD_DOT_PRODUCT
| PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA | PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) << 12;
pDevice->m_ColorOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 8) : (PS_REGISTER_R0 << 8);
}
else if (bDotAB)
{
pDevice->m_ColorOCW[dwStage] |= (PS_COMBINEROUTPUT_AB_DOT_PRODUCT | PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) << 12;
pDevice->m_ColorOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 4) : (PS_REGISTER_R0 << 4);
}
else
pDevice->m_ColorOCW[dwStage] |= bOutTemp ? (PS_REGISTER_R1 << 8) : (PS_REGISTER_R0 << 8);
return;
}
BOOL WINAPI ConstructColorCombiners(
CDevice *pDevice,
DWORD dwHWStage,
DWORD dwD3DStage)
{
BOOL bEnable = TRUE;
BOOL bStageActive = TRUE;
BOOL bDotProduct = FALSE;
BOOL bBias = FALSE;
DWORD dwShift = 0;
HRESULT hr = S_OK;
pDevice->m_ColorICW[dwHWStage] = 0;
pDevice->m_ColorOCW[dwHWStage] = 0;
switch (D3D__TextureState[dwD3DStage][D3DTSS_COLOROP])
{
default:
case D3DTOP_DISABLE:
if (dwHWStage == 0)
{
pDevice->m_ColorICW[dwHWStage] |= (PS_REGISTER_V0) << 24;
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
else
bEnable = FALSE;
bStageActive = FALSE;
break;
case D3DTOP_SELECTARG1:
hr = nvKelvinCCSelect1(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_SELECTARG2:
hr = nvKelvinCCSelect2(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_MODULATE4X:
dwShift++;
/* Each fallthrough adds one scaling bit. */
case D3DTOP_MODULATE2X:
dwShift++;
case D3DTOP_MODULATE:
hr = nvKelvinCCModulate(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_ADDSIGNED2X:
dwShift = 1;
case D3DTOP_ADDSIGNED:
bBias = TRUE;
case D3DTOP_ADD:
hr = nvKelvinCCAdd(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_SUBTRACT:
hr = nvKelvinCCSub(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_ADDSMOOTH:
hr = nvKelvinCCAddSmooth(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_BLENDDIFFUSEALPHA:
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_DIFFUSE);
break;
case D3DTOP_BLENDTEXTUREALPHA:
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TEXTURE);
break;
case D3DTOP_BLENDFACTORALPHA:
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_TFACTOR);
break;
case D3DTOP_BLENDTEXTUREALPHAPM:
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, COMBINER_PREMULTIPLIED_TEXTURE);
break;
case D3DTOP_BLENDCURRENTALPHA:
hr = nvKelvinCCBlendAlpha(pDevice, dwHWStage, dwD3DStage, D3DTA_CURRENT);
break;
case D3DTOP_PREMODULATE:
hr = nvKelvinCCPremodulate(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_MODULATEALPHA_ADDCOLOR:
hr = nvKelvinCCModulateAlpha(pDevice, dwHWStage, dwD3DStage, FALSE);
break;
case D3DTOP_MODULATECOLOR_ADDALPHA:
hr = nvKelvinCCModulateColor(pDevice, dwHWStage, dwD3DStage, FALSE);
break;
case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
hr = nvKelvinCCModulateAlpha(pDevice, dwHWStage, dwD3DStage, TRUE);
break;
case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
hr = nvKelvinCCModulateColor(pDevice, dwHWStage, dwD3DStage, TRUE);
break;
case D3DTOP_BUMPENVMAP:
case D3DTOP_BUMPENVMAPLUMINANCE:
hr = nvKelvinBumpMap(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_DOTPRODUCT3:
hr = nvKelvinCCDotProduct(pDevice, dwHWStage, dwD3DStage);
bDotProduct = TRUE;
break;
case D3DTOP_MULTIPLYADD:
hr = nvKelvinCCMultiplyAdd(pDevice, dwHWStage, dwD3DStage);
break;
case D3DTOP_LERP:
hr = nvKelvinCCLerp(pDevice, dwHWStage, dwD3DStage);
break;
}
if (hr == TSS_USES_NULL_TEXTURE)
{
if (dwHWStage == 0)
pDevice->m_ColorICW[dwHWStage] = (PS_REGISTER_V0) << 24;
else
pDevice->m_ColorICW[dwHWStage] = (PS_REGISTER_R0) << 24;
nvKelvinCCSetColorInputOne(pDevice, kelvinCombinerInputB, dwHWStage, FALSE);
}
nvConstructKelvinOutputColorCombiners(pDevice, bEnable, dwHWStage, bBias, dwShift,
bDotProduct, FALSE, D3D__TextureState[dwD3DStage][D3DTSS_RESULTARG] == D3DTA_TEMP);
return bStageActive;
}
}